python对象属性在引用时前面需要加()_python基础-面向对象进阶
实现授权的关键点就是覆盖__getattr__方法
1、通过触发__getattr__方法,找到read方法
示例1:
1 importtime2 classFileHandle:3 def __init__(self,filename,mode='r',encoding='utf-8'):4 self.file=open(filename,mode,encoding=encoding)5 self.mode=mode6 self.encoding=encoding7
8 def __getattr__(self, item):9 print(item,type(item))10 self.file.read #self.file里面有read方法
11 return getattr(self.file,item) #能过字符串来找到,并通过return返回,就找到了read方法,
12
13 f1=FileHandle('a.txt','r')14 print(f1.file)15 print(f1.__dict__) #类的字典里,没有read方法,就触发了__getattr__方法
16 print(f1.read) #找到了read方法
17
18 sys_f=open('b.txt','w+')19 print('---->',getattr(sys_f,'read')) #找到了read方法
执行结果:
1 <_io.textiowrapper name="a.txt" mode="r" encoding="utf-8">
2
3 read
4
5
6
7 {'encoding': 'utf-8', 'file': <_io.textiowrapper name="a.txt" mode="r" encoding="utf-8">, 'mode': 'r'}8
9 ---->
View Code
2、往文件里面写入内容
示例2:
1 importtime2 classFileHandle:3 def __init__(self,filename,mode='r',encoding='utf-8'):4 #self.filename=filename
5 self.file=open(filename,mode,encoding=encoding)6 self.mode=mode7 self.encoding=encoding8 defwrite(self,line):9 print('------------>',line)10 t=time.strftime('%Y-%m-%d %X')11 self.file.write('%s %s' %(t,line))12
13 def __getattr__(self, item):14 #print(item,type(item))
15 #self.file.read
16 returngetattr(self.file,item)17
18 f1=FileHandle('a.txt','w+')19 f1.write('1111111111111111\n')20 f1.write('cpu负载过高\n')21 f1.write('内存剩余不足\n')22 f1.write('硬盘剩余不足\n')
执行结果:
会创建一个a.txt的文件,并往里面写入内容:
1 2016-12-23 18:34:16 1111111111111111
2 2016-12-23 18:34:16cpu负载过高3 2016-12-23 18:34:16内存剩余不足4 2016-12-23 18:34:16 硬盘剩余不足
七、isinstance(obj,cls)和issubclass(sub,super)
1、isinstance(obj,cls) 检查是否obj是否是类cls的对象
示例:
1 classFoo(object):2 pass
3
4 obj =Foo()5
6 print(isinstance(obj,Foo))
执行结果:
1 True
2、issubclass(sub,super)检查sub类是否是supper类的派生类
示例:
1 classFoo(object):2 pass
3
4 classBar(Foo):5 pass
6
7 print(issubclass(Bar,Foo))
执行结果:
1 True
八、__getattribute__
示例1:
不存在的属性访问,就会触发__getattr__方法
1 classFoo:2 def __init__(self,x):3 self.x=x4
5 def __getattr__(self, item):6 print('执行的是我')7 #return self.__idct__[item]
8
9 f1=Foo(10)10 print(f1.x)11 f1.xxxxxx #不存在的属性访问,触发__getattr__
执行结果:
1 10
2 执行的是我
示例2:
不管是否存在,都会执行__getattribute__方法
1 classFoo:2 def __init__(self,x):3 self.x=x4
5 def __getattribute__(self, item):6 print('不管是否存在,我都会执行')7
8 f1=Foo(10)9 f1.x10 f1.xxxxxxx
执行结果:
1 不管是否存在,我都会执行2 不管是否存在,我都会执行
示例:3:
1 classFoo:2 def __init__(self,x):3 self.x=x4
5 def __getattr__(self, item): #相当于监听大哥的异常,大哥抛出导常,他就会接收。
6 print('执行的是我')7 #return self.__dict__[item]
8
9 def __getattribute__(self, item):10 print('不管是否存在,我都会执行')11 raise AttributeError('抛出异常了')12
13 f1=Foo(10)14 f1.x #结果是:10 ,调用会触发系统的
15 f1.xxxxxxx #如果不存在会触发自己定义的
执行结果:
1 不管是否存在,我都会执行2 执行的是我3 不管是否存在,我都会执行4 执行的是我
九、__setitem__,__getitem,__delitem__ (操作字典就用item的方式)
obj[‘属性’]的方式去操作属性时触发的方法
__getitem__:obj['属性'] 时触发
__setitem__:obj['属性']=属性的值 时触发
__delitem__:del obj['属性'] 时触发
示例1:
1 classFoo:2
3 def __getitem__(self, item):4 print('getitem',item)5 return self.__dict__[item]6
7 def __setitem__(self, key, value):8 print('setitem')9 self.__dict__[key]=value10
11 def __delitem__(self, key):12 print('delitem')13 self.__dict__.pop(key)14
15 f1=Foo()16 print(f1.__dict__)17 f1['name']='agon'
18 f1['age']=18
19 print('====>',f1.__dict__)20
21 del f1['name']22 print(f1.__dict__)23
24 print(f1,['age'])
执行结果:
1 {}2
3 setitem4
5 setitem6
7 ====> {'age': 18, 'name': 'agon'}8
9 delitem10
11 {'age': 18}12
13 <__main__.foo object at> ['age']
View Code
示例2:
1 classFoo:2 def __init__(self,name):3 self.name=name4
5 def __getitem__(self, item):6 print(self.__dict__[item])7
8 def __setitem__(self, key, value):9 self.__dict__[key]=value10 def __delitem__(self, key):11 print('del obj[key]时,我执行')12 self.__dict__.pop(key)13 def __delattr__(self, item):14 print('del obj.key时,我执行')15 self.__dict__.pop(item)16
17 f1=Foo('sb')18 f1['age']=18
19 f1['age1']=19
20 delf1.age121 del f1['age']22 f1['name']='alex'
23 print(f1.__dict__)
执行结果:
1 delobj.key时,我执行2
3 delobj[key]时,我执行4
5 {'name': 'alex'}
View Code
十、__str__, __repr__,__format__
1、改变对象的字符串显示__str__,__repr__ (只能是字符串的值,不能是非字符串的值)
示例1:
1 l = list('hello')2 print(1)3
4 file=open('test.txt','w')5 print(file)
执行结果:
1 1
2 <_io.textiowrapper name="test.txt" mode="w" encoding="cp936">
View Code
示例2:
__str__方法
1 #自制str方法
2 classFoo:3 def __init__(self,name,age):4 self.name=name5 self.age=age6
7 def __str__(self):8 return '名字是%s 年龄是%s' %(self.name,self.age)9
10 f1=Foo('age',18)11 print(f1) #str(f1)---->f1.__str__()
12
13 x=str(f1)14 print(x)15
16 y=f1.__str__()17 print(y)
执行结果:
1 名字是age 年龄是182 名字是age 年龄是183 名字是age 年龄是18
View Code
示例3:
__repe__方法
1 #触发__repr__方法,用在解释器里输出
2 classFoo:3 def __init__(self,name,age):4 self.name=name5 self.age=age6
7 def __repr__(self):8 return '名字是%s 年龄是%s' %(self.name,self.age)9
10 f1=Foo('agon',19)11 print(f1)
执行结果:
1 名字是agon 年龄是19
示例4:
__str__和__repe__ 共存时的用法
1 #当str与repr共存时
2 classFoo:3 def __init__(self,name,age):4 self.name=name5 self.age=age6
7 def __str__(self):8 return '名字是%s 年龄是%s' %(self.name,self.age)9
10 def __repr__(self):11 return '名字是%s 年龄是%s' %(self.name,self.age)12
13 f1=Foo('egon',19)14 #repr(f1)--->f1.__repr__()
15 print(f1) #str(f1)--->f1.__str__()---->f1.__repr__()
执行结果:
1 <__main__.foo object at>
View Code
总结:
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
2、自定制格式化字符串__format__
format的用法
示例1:
1 x = '{0}{0}{0}'.format('dog')2 print(x)
执行结果:
1 dogdogdog
不用__format__的方式实现
示例2:
1 classDate:2 def __init__(self,year,mon,day):3 self.year=year4 self.mon=mon5 self.day=day6
7 d1=Date(2016,12,26)8
9 x = '{0.year}{0.mon}{0.day}'.format(d1)10 y = '{0.year}:{0.mon}:{0.day}'.format(d1)11 z = '{0.year}-{0.mon}-{0.day}'.format(d1)12 print(x)13 print(y)14 print(z)
执行结果:
1 20161226
2 2016:12:26
3 2016-12-26
用__format__的方式实现
示例3:
1 format_dic={2 'ymd':'{0.year}:{0.month}:{0.day}',3 'm-d-y':'{0.month}-{0.day}-{0.year}',4 'y:m:d':'{0.year}:{0.month}:{0.day}',5 }6
7 classDate:8 def __init__(self,year,month,day):9 self.year=year10 self.month=month11 self.day=day12
13 def __format__(self, format_spec):14 print('我执行啦')15 print('----->',format_spec)16 if not format_spec or format_spec not informat_dic:17 format_spec='ymd'
18 fmt=format_dic[format_spec]19 returnfmt.format(self)20
21 d1=Date(2016,12,29)22 #print(format(d1)) #d1.__format__()
23 #print(format(d1))
24
25 print(format(d1,'ymd'))26 print(format(d1,'y:m:d'))27 print(format(d1,'m-d-y'))28 print(format(d1,'m-d:y'))29 print('===========>',format(d1,'sdsdddsfdsfdsfdsfdsfsdfdsfsdfds'))
执行结果:
1 我执行啦2 ----->ymd3 2016:12:29
4 我执行啦5 ----->y:m:d6 2016:12:29
7 我执行啦8 -----> m-d-y9 12-29-2016
10 我执行啦11 -----> m-d:y12 2016:12:29
13 我执行啦14 ----->sdsdddsfdsfdsfdsfdsfsdfdsfsdfds15 ===========> 2016:12:29
View Code
十一、 __slots__ (慎用)
1.__slots__是什么?是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__ 当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个 字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给 实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该 只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。 关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。更多的是用来作为一个内存优化工具。
__slots__的作用:节省内存空间
1、一个key的情况
示例1:
1 #__slots__ (作用:就是节省内存)
2 #一个key的值
3
4 classFoo:5 __slots__='name' #定义在类中的类变量,由这个类产生的实例,不在具有__dict__的属性字典,限制了创建属性
6
7 f1=Foo()8 f1.name='agon'
9 print(f1.name) #只能有一个name属性
10 print(Foo.__slots__)11 print(f1.__slots__)
执行结果:
1 agon2 name3 name
View Code
2、两个key的情况
示例2:
1 #两个key的情况
2 classFoo:3 __slots__=['name','age']4
5 f1=Foo()6
7 print(Foo.__slots__)8 print(f1.__slots__)9 f1.name='egon'
10 f1.age=17
11 print(f1.name)12 print(f1.age)13 #f1.gender='male' #会报错,加不上,#AttributeError: 'Foo' object has no attribute 'gender'
14
15 #只能定义__slots__提供的属性(这里就定义了两个属性)大家都用一个属性字典,优势就是节省内存
16 f2=Foo()17 print(f2.__slots__)18 f2.name='alex'
19 f2.age=18
20 print(f2.name)21 print(f2.age)
执行结果:
1 ['name', 'age']2 ['name', 'age']3 egon4 17
5 ['name', 'age']6 alex7 18
十二、__doc__
1、它类的描述信息
示例:
1 classFoo:2 '我是描述信息'
3 pass
4
5 print(Foo.__doc__)
2、该属性无法继承
示例:
1 #__doc__ 该属性无法继承
2
3 classFoo:4 pass
5
6 classBar(Foo):7 pass
8
9 print(Foo.__dict__) #只要加上了__doc__,该属性就无法继承给子类
10 print(Bar.__dict__) #原理就是在底层字典里面,会加一个'__doc__': None,
十三、__module__和__class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
1、创建lib/aa.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3
4 classC:5
6 def __init__(self):7 self.name = ‘SB'8
9 lib/aa.py
2、输出模块和输出类
1 from lib.aa importC2
3 obj =C()4 print obj.__module__ #输出 lib.aa,即:输出模块
5 print obj.__class__ #输出 lib.aa.C,即:输出类
十四、__del__ 析构方法(垃圾回收时自动触发)
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
1 classFoo:2 def __init__(self,name):3 self.name=name4 def __del__(self):5 print('我执行啦')6
7 f1=Foo('alex')8
9 #del f1 #删除实例会触发__del__
10 del f1.name #删除实例的属性不会触发__del__
11 print('---------------->')
执行结果:
1 ---------------->
2 我执行啦
十五、__call__
示例:
1 classFoo:2 def __call__(self, *args, **kwargs):3 print('实例执行啦 obj()')4
5 f1=Foo() #Foo下的__call__
6
7 f1() #abc下的__call__
执行结果:
1 实例执行啦 obj()
十六、 __next__和__iter__实现迭代器协议
一、什么是迭代器协议
1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)
2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。
二、python中强大的for循环机制
for循环的本质:循环所有对象,全都是使用迭代器协议。
(字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,调用了他们内部的__iter__方法,把他们变成了可迭代对象
然后for循环调用可迭代对象的__next__方法去取值,而且for循环会捕捉StopIteration异常,以终止迭代。
示例1:
1 #迭代器协议
2
3 classFoo:4 pass
5
6 l = list('hello')7 for i in l: #for循环本质就是调用他:f1.__iter__() == iter(f1)
8 print(i)
执行结果:
1 h2 e3 l4 l5 o
View Code
示例2:
1 classFoo:2 def __init__(self,n):3 self.n=n4
5 def __iter__(self): #把一个对象就成一个可迭代对象,必须有__iter__
6 returnself7
8 def __next__(self):9 self.n+=1
10 returnself.n11
12 f1=Foo(10)13 #for i in f1: #for循环本质就是调用他:f1.__iter__() == iter(f1)
14 #print(i)
15
16 print(f1.__next__())17 print(next(f1))18 print(next(f1))19 print(next(f1))20 print(next(f1))21 print(next(f1))22
23
24 for i in f1: #for循环本质就是调用他:f1.__iter__() == iter(f1)
25 print(i)
执行结果:
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
10 20
11 21
12 22
13 23
14 24
15 25
16 26
17 会一直无限循环下去.....18 下面部分省略.....
View Code
示例3:
1 classFoo:2 def __init__(self,n):3 self.n=n4
5 def __iter__(self): #把一个对象就成一个可迭代对象,必须有__iter__
6 returnself7
8 def __next__(self):9 if self.n == 13:10 raise StopIteration('终止了')11 self.n+=1
12 returnself.n13
14
15 f1=Foo(10)16
17 #print(f1.__next__())
18 #print(f1.__next__())
19 #print(f1.__next__())
20 #print(f1.__next__())
21
22 for i in f1: #f1.__iter__() == iter(f1)
23 print(i) #obj.__next__()
执行结果:
1 11
2 12
3 13
View Code
三、斐波那契数列
什么是斐波那契数列?
斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946........
这个数列从第3项开始,每一项都等于前两项之和。
示例1:
1 1 2 (相当于1+1=2) #后面这个数是前两个数之和
3 5 8 (相当于3+5=8) #后面这个数是前两个数之和
用迭代器协议的方法实现:一次产生一个值
示例2:
1 #斐波那契数列
2 classFib:3 def __init__(self):4 self._a=1
5 self._b=1
6
7 def __iter__(self):8 returnself9 def __next__(self):10 if self._a > 100:11 raise StopIteration('终止了') # >100 就抛出异常12 self._a,self._b=self._b,self._a +self._b #1+1=b; a,b=b,a(等于交换值)13 returnself._a14
15 f1=Fib()16 print(next(f1))17 print(next(f1))18 print(next(f1))19 print(next(f1))20 print(next(f1))21 print('==================================')22 for i inf1:23 print(i)
执行结果:
1 1
2 2
3 3
4 5
5 8 #print(next(f1))
6 ==================================
7 13 #for循环的值
8 21
9 34
10 55
11 89
12 144
十七、描述符(__get__,__set__,__delete__) (新式类中描述符在大型开发中常用,必须掌握。)
描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()三个方法中的一个,这也被称为描述符协议。
1 class描述符:2 def __get__():3 pass
4 def __set__():5 pass
6 def __delete__():7 pass
8
9 class类:10 name=描述符()11
12 obj=类()13 obj.name #get方法
14 obj.name='egon' #set方法
15 del obj.name #delete
描述符的三种方法:
__get__(): .调用一个属性时,触发
__set__(): .为一个属性赋值时,触发
__delete__(): 采用del.删除属性时,触发
1、定义一个描述符
示例1:
1 class Foo: #在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
2 def __get__(self,instance,owner):3 print('get方法')4 def __set__(self, instance, value):5 print('set方法')6 def __delete__(self, instance):7 print('delete方法')
2、描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
示例2:
1 classFoo:2 def __get__(self,instance,owner):3 print('===>get方法')4 def __set__(self, instance, value):5 print('===>set方法')6 def __delete__(self, instance):7 print('===>delete方法')8
9 #包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,并不会触发这三个方法
10 f1=Foo()11 f1.name='egon'
12 print(f1.name)13 delf1.name14 #疑问:何时,何地,会触发这三个方法的执行
3、描述符应用之何时?何地?
示例3:
1 #描述符应用之何时?何地?
2
3 #描述符Str
4 classFoo:5 def __get__(self,instance,owner):6 print('===>get方法')7 def __set__(self, instance, value):8 print('===>set方法')9 def __delete__(self, instance):10 print('===>delete方法')11
12
13 classBar:14 x=Foo() #在何地?
15
16 print(Bar.__dict__)17
18 #在何时?
19 b1=Bar()20 #b1.x #调用就会触发上面的get方法
21 #b1.x=1 #赋值
22 #del b1.x
23 print(b1.x) #触发了描述器里面的get方法,得到None
24 b1.x=1 #触发了描述器里面的set方法,得到{}
25 print(b1.__dict__) #写到b1的属性字典中
26
27 del b1.x #打印===>delete方法
执行结果:
1 {'x': <__main__.foo object at>, '__weakref__': , '__dict__': , '__doc__': None, '__module__': '__main__'}2
3 ===>get方法4
5 None6
7 ===>set方法8
9 {}10
11 ===>delete方法
View Code
4、描述符分两种
一、数据描述符:至少实现了__get__()和__set__()两种方法
示例:
1 classFoo:2 def __set__(self, instance, value):3 print('set')4 def __get__(self, instance, owner):5 print('get')
二、非数据描述符:没有实现__set__()方法
示例:
1 classFoo:2 def __get__(self, instance, owner):3 print('get')
5、注意事项:
一、描述符本身应该定义成新式类,被代理的类也应该是新式类
二、必须把描述符定义成另外一个类触发的类属性,不能为定义到构造函数中
示例:
1 classFoo:2 def __get__(self,instance,owner):3 print('===>get方法')4 def __set__(self, instance, value):5 print('===>set方法')6 def __delete__(self, instance):7 print('===>delete方法')8
9 classBar:10 x=Foo() #定义一个描述符
11 def __init__(self,n):12 self.x=n13
14 b1=Bar(10) #触发set方法
15 print(b1.__dict__)
执行结果:
1 ===>set方法2 {}
三、要严格遵循该优先级,优先级由高到底分别是
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()
类属性>数据描述符
示例:
1 classFoo:2 def __get__(self,instance,owner):3 print('===>get方法')4 def __set__(self, instance, value):5 print('===>set方法')6 def __delete__(self, instance):7 print('===>delete方法')8
9 classBar:10 x=Foo() #调用foo()属性,会触发get方法
11
12 print(Bar.x) #类属性比描述符有更高的优先级,会触发get方法
13 Bar.x=1 #自己定义了一个类属性,并赋值给x,跟描述符没有关系,所以他不会触发描述符的方法
14 #print(Bar.__dict__)
15 print(Bar.x)
执行结果:
1 ===>get方法2 None3 1
数据描述符>实例属性
示例1:
1 #有get,set就是数据描述符,数据描述符比实例属性有更高的优化级
2
3 classFoo:4 def __get__(self,instance,owner):5 print('===>get方法')6 def __set__(self, instance, value):7 print('===>set方法')8 def __delete__(self, instance):9 print('===>delete方法')10
11 classBar:12 x = Foo() #调用foo()属性,会触发get方法
13
14 b1=Bar() #在自己的属性字典里面找,找不到就去类里面找,会触发__get__方法
15 b1.x #调用一个属性的时候触发get方法
16 b1.x=1 #为一个属性赋值的时候触发set方法
17 del b1.x #采用del删除属性时触发delete方法
执行结果:
1 1 ===>get方法2 2 ===>set方法3 3 ===>delete方法
示例2:
1 classFoo:2 def __get__(self,instance,owner):3 print('===>get方法')4
5 def __set__(self, instance, value):6 pass
7
8 classBar:9 x =Foo()10
11 b1=Bar()12 b1.x=1 #触发的是非数据描述符的set方法
13 print(b1.__dict__)
执行结果:
1 {} #数据描述符>实例属性
类属性>数据描述符>实例属性
1 #类属性>数据描述符>实例属性
2
3 classFoo:4 def __get__(self,instance,owner):5 print('===>get方法')6 def __set__(self, instance, value):7 print('===>set方法')8 def __delete__(self, instance):9 print('===>delete方法')10
11 classBar:12 x = Foo() #调用foo()属性,会触发get方法
13
14 b1=Bar() #实例化
15 Bar.x=11111111111111111 #不会触发get方法
16 b1.x #会触发get方法
17
18 del Bar.x #已经给删除,所以调用不了!报错:AttributeError: 'Bar' object has no attribute 'x'
19 b1.x
非数据描述符
示例1:
1 #非数据描述符没有set方法
2 classFoo:3 def __get__(self,instance,owner):4 print('===>get方法')5
6 def __delete__(self, instance):7 print('===>delete方法')8
9 classBar:10 x =Foo()11
12 b1=Bar()13 b1.x #自己类中没有,就会去Foo类中找,所以就会触发__get__方法
执行结果:
===>get方法
示例2:
1 #实例属性>非数据描述符
2 classFoo:3 def __get__(self,instance,owner):4 print('===>get方法')5
6 classBar:7 x =Foo()8
9 b1=Bar()10 b1.x=1
11 print(b1.__dict__) #在自己的属性字典里面,{'x': 1}
执行结果:
1 {'x': 1}
非数据描述符>找不到
1 #非数据描述符>找不到
2
3 classFoo:4 def __get__(self,instance,owner):5 print('===>get方法')6
7 classBar:8 x =Foo()9 def __getattr__(self, item):10 print('------------>')11
12 b1=Bar()13 b1.xxxxxxxxxxxxxxxxxxx #调用没有的xxxxxxx,就会触发__getattr__方法
执行结果:
1 ------------> #解发__getattr__方法
四、描述符应用
示例1:
1 classTyped: #有__get__,__set__,__delete__ 就是:数据描述符2 def __get__(self, instance,owner):3 print('get方法')4 print('instance参数【%s】' %instance)5 print('owner参数【%s】' %owner)6
7 def __set__(self, instance, value):8 print('set方法')9 print('instance参数【%s】' %instance)10 print('value参数【%s】' %value)11
12 def __delete__(self, instance):13 print('delete方法')14 print('instance参数【%s】'%instance)15
16
17 classPeople:18 name=Typed() #设置代理(代理的就是name属性)19 def __init__(self,name,age,salary):20 self.name=name #触发的是代理
21 self.age=age22 self.salary=salary23
24 p1=People('alex',13,13.3)25 #'alex' #触发set方法
26 p1.name #触发get方法,没有返回值
27 p1.name='age' #触发set方法
28 print(p1.__dict__) #{'salary': 13.3, 'age': 13}
执行结果:
1 set方法2 instance参数【<__main__.people object at>】3 value参数【alex】4 get方法5 instance参数【<__main__.people object at>】6 owner参数【】7 set方法8 instance参数【<__main__.people object at>】9 value参数【age】10 {'salary': 13.3, 'age': 13}
View Code
示例2:给字典属性传值
1 #给字典里面传入值
2 classTyped:3 def __init__(self,key):4 self.key=key5
6 def __get__(self, instance, owner):7 print('get方法')8 return instance.__dict__[self.key] #触发get方法,会返回字典的值
9
10 def __set__(self, instance, value):11 print('set方法')12 instance.__dict__[self.key]=value #存在p1的属性字典里面
13
14 def __delete__(self, instance):15 print('delete方法')16 instance.__dict__.pop(self.key)17
18 classPeople:19 name=Typed('name') #name属性被Typed给代理了,t1._set_() self._set__()
20 def __init__(self,name,age,salary):21 self.name=name22 self.age=age23 self.salary=salary24
25 p1=People('alex',13,13.3)26
27 #打印实例字典
28 print(p1.__dict__)29
30 #创建属性,给name赋值,相当于修改了name字典的值
31 p1.name='egon' #触发的是set方法
32 print(p1.__dict__)33
34 #删除name属性
35 print(p1.__dict__)36 del p1.name #触发的是delete方法
37 print(p1.__dict__)
执行结果:
1 #打印实例属性字典
2 set方法3 {'age': 13, 'salary': 13.3, 'name': 'alex'}4
5 #修改name字典的值
6 set方法7 {'age': 13, 'salary': 13.3, 'name': 'egon'}8
9 #删除name属性
10 delete方法11 {'age': 13, 'salary': 13.3}
示例3:
实现类型检测的两种方法:
方法一:用return的方式
1 #判断他传入的值是不是字符串类型
2 classTyped:3 def __init__(self,key):4 self.key=key5
6 def __get__(self, instance, owner):7 print('get方法')8 return instance.__dict__[self.key] #触发get方法,会返回字典的值
9
10 def __set__(self, instance, value):11 print('set方法')12 if notisinstance(value,str):13 print('你传入的类型不是字符串,错误')14 return #return的作用就是终止这个属性字典,让他的值设置不进字典中。
15 instance.__dict__[self.key]=value #存在p1的属性字典里面
16
17 def __delete__(self, instance):18 print('delete方法')19 instance.__dict__.pop(self.key)20
21 classPeople:22 name=Typed('name') #name属性被Typed给代理了,t1._set_() self._set__()
23 def __init__(self,name,age,salary):24 self.name=name25 self.age=age26 self.salary=salary27
28 #正常的情况下__dict__里面有没有'name':'alex'
29 p1=People('alex',13,13.3)30 print(p1.__dict__) #触发set方法,得到的值是{'salary': 13.3, 'name': 'alex', 'age': 13}
31
32 #不正常的情况下,修改'name':213 不等于字符串,改成了int类型
33 p1=People(213,13,13.3)34 print(p1.__dict__) #触发set方法,得到的值是{'salary': 13.3, 'name': 'alex', 'age': 13}
执行结果:
1 set方法2 {'salary': 13.3, 'age': 13, 'name': 'alex'}3
4 set方法5 你传入的类型不是字符串,错误6 {'salary': 13.3, 'age': 13}
方法二:用raise抛出异常的方式,判断他传入的值是不是字符串类型,(写死了,不灵活)
1 #用抛出异常的方式,判断他传入的值是不是字符串类型
2 classTyped:3 def __init__(self,key):4 self.key=key5
6 def __get__(self, instance, owner):7 print('get方法')8 return instance.__dict__[self.key] #触发get方法,会返回字典的值
9
10 def __set__(self, instance, value):11 print('set方法')12 if notisinstance(value,str): #判断是否是字符串类型13 #方法一:return的方式
14 # print('你传入的类型不是字符串,错误')
15 # return #return的作用就是终止这个属性字典,让他的值设置不进字典中。
16 #方法二:
17 raise TypeError('你传入的类型不是字符串') ##用抛出异常的方式,判断他传入的值是不是字符串类型
18 instance.__dict__[self.key]=value #存在p1的属性字典里面
19
20 def __delete__(self, instance):21 print('delete方法')22 instance.__dict__.pop(self.key)23
24 classPeople:25 name=Typed('name') #name属性被Typed给代理了,t1._set_() self._set__()
26 def __init__(self,name,age,salary):27 self.name=name28 self.age=age29 self.salary=salary30
31 #正常的情况下__dict__里面有没有'name':'alex'
32 #p1=People('alex',13,13.3)
33 #print(p1.__dict__) #触发set方法,得到的值是{'salary': 13.3, 'name': 'alex', 'age': 13}
34
35 #不正常的情况下,修改'name':213 不等于字符串,改成了int类型
36 p1=People(213,13,13.3)37 print(p1.__dict__) #触发set方法,得到的值是{'salary': 13.3, 'name': 'alex', 'age': 13}
执行结果:
1 Traceback (most recent call last):2 set方法3 File "D:/python/day28/5-1.py", line 219, in
4 {'name': 'alex', 'age': 13, 'salary': 13.3}5 set方法6 p1=People(213,13,13.3)7 File "D:/python/day28/5-1.py", line 210, in __init__
8 self.name=name9 File "D:/python/day28/5-1.py", line 200, in __set__
10 raise TypeError('你传入的类型不是字符串')11 TypeError: 你传入的类型不是字符串
类型检测加强版
示例:4:用raise抛出异常的方式,判断传入的值是什么类型,同时可以判断多个属性(推荐写法)
1 #用抛出异常的方式,判断他传入的值是什么类型 (不写死的方式,判断传入值的类型)
2 classTyped:3 def __init__(self,key,expected_type):4 self.key=key5 self.expected_type=expected_type6
7 def __get__(self, instance, owner):8 print('get方法')9 return instance.__dict__[self.key] #触发get方法,会返回字典的值
10
11 def __set__(self, instance, value):12 print('set方法')13 if notisinstance(value,self.expected_type):14 raise TypeError('%s 你传入的类型不是%s' %(self.key,self.expected_type)) #用抛出异常的方式,判断他传入的值是什么类型,同时可以判断多个属性的类型
15 instance.__dict__[self.key]=value #存在p1的属性字典里面
16
17 def __delete__(self, instance):18 print('delete方法')19 instance.__dict__.pop(self.key)20
21 classPeople:22 name=Typed('name',str) #name设置代理Typed
23 age=Typed('age',int) #age设置代理Typed
24 def __init__(self,name,age,salary):25 self.name=name #alex传给代理,会触发set方法
26 self.age=age #age传给代理,会触发set方法
27 self.salary=salary28
29 #name是字符串,age是整型,salary必须是浮点数
30 #正确的方式
31 p1=People('alex',13,13.3)32
33 #传入错误的类型,会判断传入值的类型
34 #name要求传入的srt,但这里传入的是整型,所以会报错,说你传入的不是srt类型
35 p1=People(213,13,13.3)
执行结果:
1 set方法2 File "D:/python/day28/5-1.py", line 220, in
3 p1=People(213,13,13.3)4 set方法5 File "D:/python/day28/5-1.py", line 210, in __init__
6 set方法7 self.name=name8 File "D:/python/day28/5-1.py", line 199, in __set__
9 raise TypeError('%s 你传入的类型不是%s' %(self.key,self.expected_type)) #用抛出异常的方式,判断他传入的值是什么类型
10
11 TypeError: name 你传入的类型不是
View Code
十八、__enter__和__exit__
1、操作文件写法
1 with open('a.txt') as f:2 '代码块'
2、上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
1 classOpen:2 def __init__(self,name):3 self.name=name4
5 def __enter__(self):6 print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')7 #return self
8 def __exit__(self, exc_type, exc_val, exc_tb):9 print('with中代码块执行完毕时执行我啊')10
11
12 with Open('a.txt') as f: #with语句,触发__enter__,返回值赋值给f13 print('=====>执行代码块')14 #print(f,f.name)
执行结果:
1 出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量2 =====>执行代码块3 with中代码块执行完毕时执行我啊
3、执行代码块
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
没有异常的情况下,整个代码块运行完毕后去触发__exit__,它的三个参数都会执行
1 classFoo:2 def __init__(self,name):3 self.name=name4
5 def __enter__(self):6 print('执行enter')
7 returnself #2、拿到的结果是self,并赋值给f8
9 def __exit__(self, exc_type, exc_val, exc_tb): #4、触发__exit__,然后执行print()10 print('执行exit')11 print(exc_type)12 print(exc_val)13 print(exc_tb)14
15
16 with Foo('a.txt') as f: #1、with触发的是__enter__,拿到的结果是self并赋值给f;17 print(f) #3、然后会执行with代码块,执行完毕后
18 print(assfsfdsfdsfdsfffsadfdsafdsafdsafdsafdsafdsafdsafdsad)
19 print(f.name)
20 print('000000000000000000000000000000000000000000000000000000')
执行结果:
1 执行enter2 Traceback (most recent call last):3 <__main__.foo object at>
4 File "D:/python/day28/s1.py", line 56, in
5 执行exit6 print(assfsfdsfdsfdsfffsadfdsafdsafdsafdsafdsafdsafdsafdsad) #触发__exit__
7
8 NameError: name 'assfsfdsfdsfdsfffsadfdsafdsafdsafdsafdsafdsafdsafdsad' is notdefined9 name 'assfsfdsfdsfdsfffsadfdsafdsafdsafdsafdsafdsafdsafdsad' is notdefined10
View Code
4、有返回值
如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
1 classFoo:2 def __init__(self,name):3 self.name=name4
5 def __enter__(self):6 print('执行enter')
7 returnself8 '''class、异常值、追踪信息'''
9 def __exit__(self, exc_type, exc_val, exc_tb): #2、有异常的时候,就会触发__exit__方法10 print('执行exit')11 print(exc_type)12 print(exc_val)13 print(exc_tb)14 return True #3、没有return True就会报错,如果有return True异常自己吃了,不报异常
15
16 with Foo('a.txt') as f:17 print(f)
18 print(assfsfdsfdsfdsfffsadfdsafdsafdsafdsafdsafdsafdsafdsad) #1、有异常的情况,他就会触发__exit__
19 print(f.name) #不执行这行,直接打印下面那行
20 print('000000000000000000000000000000000000000000000000000000') #4、最后打印这行
执行结果:
1 执行enter2 <__main__.foo object at>
3 执行exit4
5 name 'assfsfdsfdsfdsfffsadfdsafdsafdsafdsafdsafdsafdsafdsad' is notdefined6
7 000000000000000000000000000000000000000000000000000000
View Code
总结:
with obj as f:
'代码块'
1.with obj ---->触发obj.__enter__(),拿到返回值
2.as f----->f=返回值、
3.with obj as f 等同于 f=obj.__enter__()
4.执行代码块
一:没有异常的情况下,整个代码块运行完毕后去触发__exit__,它的三个参数都为None
二:有异常的情况下,从异常出现的位置直接触发__exit__
a:如果__exit__的返回值为True,代表吞掉了异常
b:如果__exit__的返回值不为True,代表吐出了异常
c:__exit__的的运行完毕就代表了整个with语句的执行完毕
用途:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接(TCP协议建连接、传输数据、关连接)和锁(进程,线程)的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处。
十九、类的装饰器
示例1:类的装饰器基本原理
1 #示例1
2 defdeco(func): #高阶函数3 print('===================')4 return func #fuc=test
5
6 @deco #装饰器test=deco(test)
7 deftest():8 print('test函数运行')9 test() #运行test
执行结果:
1 ===================
2 test函数运行
示例2:类的装饰器基本原理
1 defdeco(obj):2 print('============',obj)3 obj.x=1 #增加属性
4 obj.y=2
5 obj.z=3
6 returnobj7
8 @deco #Foo=deco(Foo) #@deco语法糖的基本原理(语法糖可以在函数前面加,也可以在类的前面加)
9 classFoo: #类的装饰器10 pass
11
12 print(Foo.__dict__) #加到属性字典中
执行结果:
1 ============
2 {'__module__': '__main__', 'z': 3, 'x': 1, '__dict__': , '__doc__': None, '__weakref__': , 'y': 2}
用法总结:@deco语法糖可以在函数前面加,也可以在类的前面加
示例3:一切皆对象
1 defdeco(obj):2 print('==========',obj)3 obj.x=1
4 obj.y=2
5 obj.z=3
6 returnobj7
8 #@deco #Foo=deco(test)
9 deftest():10 print('test函数')11 test.x=1 #但没有人会这么做,只是验证一切皆对象
12 test.y=1
13 print(test.__dict__)
执行结果:
1 {'x': 1, 'y': 1}
示例4:直接传值并加到字典中
1 def Typed(**kwargs): #负责接收参数
2 def deco(obj): #局部作用域
3 obj.x=1
4 obj.y=2
5 obj.z=3
6 returnobj7 print('====>',kwargs) #外层传了个字典进来,就是: 'y': 2, 'x': 1,
8 returndeco9
10 @Typed(x=1,y=2,z=3) #typed(x=1,y=2,z=3)--->deco 函数名加()就是运行Typed函数
11 classFoo:12 pass
执行结果:
1 ====> {'y': 2, 'x': 1, 'z': 3}
示例5:类的装饰器增强版
1 def Typed(**kwargs): #Type传过来的参数,就是name='egon',kwargs包含的就是一个字典2 defdeco(obj):3 for key,val inkwargs.items(): #key=name,val=age4 setattr(obj,key,val) #obj=类名,key=name,val=age5 returnobj #返回类本身:obj,就相当于给类加了个属性6 returndeco7
8 @Typed(x=1,y=2,z=3) #1、typed(x=1,y=2,z=3)--->deco 2、@deco--->Foo=deco(Foo)
9 classFoo:10 pass
11 print(Foo.__dict__)12
13 @Typed(name='egon') #@deco---->Bar=deco(Bar),重新赋值给了Bar14 classBar:15 pass
16 print(Bar.name) #最后打印name,就得到egon
执行结果:
1 {'y': 2, '__dict__': , 'z': 3, '__weakref__': , '__module__': '__main__','x': 1, '__doc__': None}2
3 egon
实现:类型检测控制传入的值是什么类型
1、用raise抛出异常的方式实现
2、用类加装饰器实现 (这种方法更高级)
示例6:类加装饰器的应用
示例如下:
1、给类加装饰器,实现控制传入的类型(推荐写法) 可以参考: 示例:4:用raise抛出异常的方式,判断传入的值是什么类型,同时可以判断多个属性。
1 #给类加装饰器,实现控制传入的类型
2
3 classTyped:4 def __init__(self,key,expected_type):5 self.key=key6 self.expected_type=expected_type7
8 def __get__(self, instance, owner):9 print('get方法')10 return instance.__dict__[self.key]11
12 def __set__(self, instance, value):13 print('set方法')14 if notisinstance(value,self.expected_type):15 raise TypeError('%s 传入的类型不是%s' %(self.key,self.expected_type))16 instance.__dict__[self.key]=value17
18 def __delete__(self, instance):19 print('delete方法')20 instance.__dict__.pop(self.key)21
22 def deco(**kwargs): #kwargs={'name':str,'age':int}
23 def wrapper(obj): #obj=People
24 for key,val in kwargs.items(): #(('name',str),('age',int))
25 #print(obj,key)
26 setattr(obj,key,Typed(key,val)) #给People设置类属性
27 returnobj28 returnwrapper29
30 #给类加装饰器,加了装饰器,指定了什么类型,就必须传入什么类型的值,否则就会报错
31 @deco(name=str,age=int,salary=float) #@wrapper ===>People=wrapper(People) #实现这个功能的重点在这里
32 classPeople:33 #name=Typed('name',int)
34 def __init__(self,name,age,salary):35 self.name=name36 self.age=age37 self.salary=salary38
39 #name=srt,age=int,salary=float
40#传入的是正确的类型,所以不会报错。
41 p1 = People('alex', 13, 13.3)42 print(People.__dict__)43
44 #age设置成了int型,我们传入的是字符串类型,所以会报错:TypeError: age 传入的类型不是
45 #p1=People('alex','13',13.3)
46 #print(People.__dict__)
执行结果:
1 #传入正确类型的值
2
3 set方法4 set方法5 set方法6 {'__doc__': None, 'name': <__main__.typed object at>, '__dict__': , '__module__': '__main__', '__init__': , 'salary': <__main__.typed object at>, '__weakref__': , 'age': <__main__.typed object at>}7
8 #传入错误类型的值,会报错,并提示你传入值的类型。
示例7:利用描述自定制property
1 classLazyproperty:2 def __init__(self,func):3 print('===========>',func)4 self.func=func5 def __get__(self,instance,owner):6 print('get')7 print('instance')8 print('owner')9 res=self.func(instance)10 returnres11 classRoom:12 def __init__(self,name,width,length):13 self.name=name14 self.width=width15 self.length=length16 @Lazyproperty17 defarea(self):18 return self.width *self.length19
20 r1=Room('厕所',1,1)21 print(r1.area)
执行结果:
1 get2 instance3 owner4 1
示例8:利用描述符实现延迟计算
1 classLazyproperty:2 def __init__(self,func):3 print('===========>',func)4 self.func=func5 def __get__(self,instance,owner):6 print('get')7 print('instance')8 print('owner')9 res=self.func(instance)10 returnres11 classRoom:12 def __init__(self,name,width,length):13 self.name=name14 self.width=width15 self.length=length16 @Lazyproperty17 defarea(self):18 return self.width *self.length19
20 r1=Room('厕所',1,1)21 print(r1.area)
示例9:非数据描述符
1 classLazyproperty:2 def __init__(self,func):3 self.func=func4
5 def __get__(self, instance, owner):6 print('get')7
8 if instance isNone:9 returnself10 res=self.func(instance)11 setattr(instance,self.func.__name__,res)12 returnres13
14 classRoom:15 def __init__(self,name,width,length):16 self.name=name17 self.width=width18 self.length=length19
20 @Lazyproperty21 defarea(self):22 return self.width *self.length23 @property24 defareal(self):25 return self.width *self.length26
27 r1=Room('厕所',1,1)28
29 print(r1.area)30 print(r1.__dict__)31
32 print(r1.area)33 print(r1.area)34 print(r1.area)35 print(r1.area)36 print(r1.area)37 print(r1.area)38 print(r1.area)39 print(r1.area)
执行结果:
1 get2 1
3 {'area': 1, 'length': 1, 'name': '厕所', 'width': 1}4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 1
二十、元类(metaclass)
1、示例:
1 classFoo:2 pass
3
4 f1=Foo() #f1是通过Foo类实例化的对象
python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)
上例可以看出f1是由Foo这个类产生的对象,而Foo本身也是对象,那它又是由哪个类产生的呢?
1 classFoo:2 pass
3
4 f1=Foo()5
6 print(type(f1)) #
7 print(type(Foo)) #类的类就是
8
9 classBar:10 pass
11 print(type(Bar)) #
执行结果:
1 #type函数可以查看类型,也可以用来查看对象的类,二者是一样的。
2
3
4
2、什么是元类?
元类是类的类,是类的模板
元类是用来控制如何创建类的,正如类是创建对象的模板一样
元类的实例为类,正如类的实例为对象(f1对象是Foo类的一个实例,Foo类是 type 类的一个实例)
type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象
3、创建类的两种方式
方式一:
1 classFoo:2 pass
3 print(Foo)4 print(Foo.__dict__)
执行结果:
1
2 {'__module__': '__main__', '__doc__': None, '__dict__': , '__weakref__': }
方式二:
1 #type就是类的类,用type()实例化的结果,就是产生一个类
2 #用type和class生成的类是一样的效果。
3
4 def __init__(self,name,age):5 self.name=name6 self.age=age7
8 deftest(self):9 print('=======执行的是test=====>')10
11 FFo=type('FFo',(object,),{'x':1,'__init__':__init__,'test':test})12 print(FFo)13 #print(FFo.__dict__)
14
15 f1=FFo('alex',18)16 print(f1.x) #调的是类属性
17 print(f1.name) #调name
18 f1.test() #调方法
执行结果:
1
2 1
3 alex4 =======执行的是test=====>
4、一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类。
示例: 自定制元类
1 classMyType(type):2 def __init__(self,a,b,c):3 print('元类的构造函数执行')4
5 def __call__(self, *args, **kwargs):6 obj=object.__new__(self) #object.__new__(Foo)-->f1
7 self.__init__(obj,*args,**kwargs) #Foo.__init__(f1,*arg,**kwargs)
8 returnobj9
10 class Foo(metaclass=MyType): #Foo=MyType(Foo,'Foo',(),{})---》__init__
11 def __init__(self,name):12 self.name=name #f1.name=name
13 f1=Foo('alex')
执行结果:
1 元类的构造函数执行
python对象属性在引用时前面需要加()_python基础-面向对象进阶相关推荐
- python对象属性是与数据有关的项目_python之对象产生,属性(定义的值)的查找原则,对象绑定关系...
例1: 通过外部定义一个函数也可以传值进去 class OldboyStudent: school='oldboy' def choos ...
- 7天入门Python 3 — Python对象属性及核心数据类型
专栏自述:随着这几年机器学习火爆,楼主写了Java好多年,python其实也会写,但是缺乏系统性梳理,所以搞一个python栏目,系统性梳理的同时也把python的知识做一些梳理,欢迎查阅,欢迎一起学 ...
- 详解Python对象属性
在面向对象编程中,公开的数据成员可以在外部随意访问和修改,很难控制用户修改时新数据的合法性.解决这一问题的常用方法是定义私有数据成员,然后设计公开的成员方法来提供对私有数据成员的读取和修改操作,修改私 ...
- 当对象或对象属性为空时,如何安全给对象或对象属性添加默认值
今天遇到的问题,也是写代码的习惯问题,逻辑没有问题,但不规范,也不安全, 容易出现漏洞. 先将代码贴出: String isPrintLogo = vodInfoDto.getIsPrintLogo( ...
- python对象属性查看
在很多情况下,我们需要查看一个对象的属性,包括它是什么类型或者都有哪些方法?今天就总结一下在Python中有哪些函数可以查看对象属性. 1. type() type函数用于基本类型的判断,比如int, ...
- Java对性别默认值为男_当对象或对象属性为空时,如何安全给对象或对象属性添加默认值...
今天遇到的问题,也是写代码的习惯问题,逻辑没有问题,但不规范,也不安全, 容易出现漏洞. 先将代码贴出: String isPrintLogo = vodInfoDto.getIsPrintLogo( ...
- python程序开发的各个阶段_python基础----面向对象的程序设计(五个阶段、对小白的忠告、关于OOP常用术语)、类、对象...
抽象指对现实世界问题和实体的本质表现,行为和特征建模,建立一个相关的子集,可以用于 绘程序结构,从而实现这种模型.抽象不仅包括这种模型的数据属性,还定义了这些数据的接口. 对某种抽象的实现就是对此数据 ...
- python基础程序设计与面向对象程序设计_python基础——面向对象的程序设计
python基础--面向对象的程序设计 1 什么是面向对象的程序设计 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...
- python定义一个student类、有下面的_Python基础(小白教程)之面向对象
原标题:Python基础(小白教程)之面向对象 Python的类 > 在这门语言中,类使用 class 语句来定义.在类中包含了一系列语句,比如赋值语句,def 定义函数等.从面向对象的角度看, ...
最新文章
- tensorflow笔记
- python 忽略 异常_如何忽略Python中的异常?
- linux下安装nginx的采坑记录
- 序列复杂度怎么看_每日算法系列【LeetCode 376】摆动序列
- 网络编程1-初探winSocket
- 互联网35岁中年危机的来龙去脉
- 实战:判断mysql中当前用户的连接数-分组筛选
- 索引 2 超出范围。_重点推荐:音响灯光行业搜索引擎推广教学
- 如何在VSCode上新建Flutter项目【两步搞定】
- 怎么清理c盘语言文件,怎么清理c盘垃圾
- Android fastboot下载模式或reboot流程解析
- 临沂最美乡村医生彭玉梅:救人遇车祸身亡
- Python3 + Scrapy爬链家深圳成交房信息
- Nginx配置文件目录实现pdf文件预览及下载
- image could not be accessed on a registry to record its digest
- 【STM32】实战2—用STM32产生PWM信号驱动舵机MG996R(一)
- [leetcode]初级算法——动态规划
- 使用传统AV屏幕用作树莓派屏幕
- QQ浏览器及360浏览器兼容模式下怎么处理sessionStorage数据
- JAVA线上问题排查及常用命令
热门文章
- Aixs2发布webservice服务
- [Cocoa]深入浅出Cocoa之Core Data(2)- 手动编写代码
- css 一些 常用布局
- Jenkins构建 netcore5.0 项目时出现NU3028/NU3037错误的解决方案
- 解决svn:E200030: sqlite[S11]:database disk image is malformed
- docker centos ssh
- vue js xlsx 读取 本地 excel
- Flex与JavaScript的交互:调用JavaScipt或者被JavaScript调用
- linux客户端无法绑定端口号,为什么Linux客户端的情况下不支持端口共用?
- spring框架(六)之拦截器