面向对象进阶
一:isinstance(obj,cls)和issubclass(sub,super)
- isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo: pass f1=Foo() print(isinstance(f1,Foo))
2. issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo: pass f1=Foo() print(isinstance(f1,Foo)) class Bar(Foo): pass b1=Bar() print(issubclass(Bar,Foo)) print(isinstance(b1,Foo)) print(type(b1)) #<class '__main__.Bar'>
二:getattribute
class Foo: def __init__(self,x): self.x=x def __getattr__(self, item): print('执行的是getattr') def __getattribute__(self, item): print('执行的是getattribute') raise AttributeError('抛出异常了') f1=Foo(10) f1.xxxxx f1.x
属性有没有都会触发getattribute,当由于raise AttributeError('抛出异常了'),使得触发getattr
当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError
三:item方法
- __getitem__
- __setitem__
- __delitem__
class Foo: def __getitem__(self, item): print('getitem',item) return self.__dict__[item] def __setitem__(self, key, value): print('setitem') self.__dict__[key]=value def __delitem__(self, key): print('delitem') self.__dict__.pop(key) f1=Foo() # print(f1.__dict__) f1['name']='egon' f1['age']=18 print(f1.__dict__) # del f1['name'] print(f1.__dict__) print(f1['age'])
item 方法适用于字典触发,而 .形式适用于attr属性触发方法
四:改变对象的字符串显示
class Foo: def __init__(self,name,age): self.name=name self.age=age def __str__(self): #str(f1)-->f1.__str__,print()触发 return '名字是%s 年纪是%s'%(self.name,self.age) #自己控制打印信息 f1=Foo('egon',18) print(f1) #<__main__.Foo object at 0x005B2510>;名字是egon 年纪是18
class Foo: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return '这是str' def __repr__(self): #repr(f1)-->f1.__repr__,应用在解释器中 return '名字是%s 年纪是%s'%(self.name,self.age) #自己控制打印信息 f1=Foo('egon',18) print(f1) #str(f1)--->f1.__str__()---->f1.__repr___()
__str__ :由print触发 ===》obj.__str__()
__repr__:使用于交互式解释器====》obj.__repr__()
如果__str__没有定义,就使用__repr__来代替输出
notice : 这两种方法返回值必须是字符串,否则抛出异常
自定制格式化方法format
x='{0}{0}{0}'.format('dog') print(x)
#dogdogdog
class Data: def __init__(self,year,mon,day): self.year=year self.mon=mon self.day=day d1=Data(2017,3,12) x='{0.year}{0.mon}{0.day}'.format(d1) #d1.format y='{0.year}:{0.mon}:{0.day}'.format(d1) z='{0.year}-{0.mon}-{0.day}'.format(d1) print(x) print(y) print(z)
#2017312
2017:3:12
2017-3-12
format_dic={ 'ymd':'{0.year}{0.mon}{0.day}', 'm-d-y':'{0.mon}{0.day}{0.year}', 'y:m:d':'{0.year}{0.mon}{0.day}', } class Data: def __init__(self,year,mon,day): self.year=year self.mon=mon self.day=day def __format__(self, format_spec): print('我执行啦') print('--->',format_spec) if not format_spec or format_spec not in format_dic: format_spec='ymd' fm=format_dic[format_spec] return fm.format(self) d1=Data(2017,3,12) print(format(d1,'ymd')) print(format(d1,'m-d-y')) print(format(d1,'m:d:y')) print(format(d1,'m-d:y'))
五:__slots__ :定义类变量,效果由类产生的属性不在具有__dict__属性
属性很少的类,但是实例很多,为了节省内存可以使用__slots__取代实例的__dict__
class Foo: __slots__=['name','age']# 属性字典的形式{'name':None,'age':None} __slots__ = 'name' # {'name':None,'age':None} f1=Foo() # print(f1.__dict__) #报错,取消了__dict__ print(f1.__slots__) #['name', 'age'] f2=Foo() print(f2.__slots__) f2.name='alex' f2.age=19 print(f2.name) print(f2.age)
#f1与f2都没有属性字典__dict__了,统一归__slots__管,节省内存
六:
1. __doc__ 改属性无法被继承,文档注释
class Foo: '我是描述信息' pass print(Foo.__doc__) class Foo: '我是描述信息' pass class Bar(Foo): pass print(Bar.__doc__) #改属性无法继承给子类 print(Foo.__doc__)
2. __module__表示当前操作的对象在那个模块
__class__表示当前操作的对象的类是什么
from lib.aa import C c1=C() print(c1.name) print(c1.__module__) print(c1.__class__) #aa.py class C: def __init__(self): self.name='SB'
3. __del__析构方法 当对象在内存中被释放时,自动触发执行,只在实例被删除时触发
class Foo: def __init__(self,name): self.name=name def __del__(self): print('wozhixing') f1=Foo('alex') # del f1 # print('---------------->') #先执行后打印 del f1.name #只有实例被删除时才触发,所以先打印,然后再删除 这里的实例是f1 print('---------------->') #先打印后删除
4. __call__对象后面加括号,触发执行
class Foo: def __call__(self, *args, **kwargs): print('实例执行啦') f1=Foo() f1() #Foo下的__cal__ Foo()#abc下的__cal__
5. 迭代器协议
class Foo: def __init__(self,n): self.n=n def __iter__(self): #把一个对象变成可迭代对象 return self def __next__(self): if self.n == 13: raise StopIteration('终止了') self.n+=1 return self.n f1=Foo(10) print(iter(f1)) #第一种方法 for i in f1: #f1.__iter__() == iter(f1) print(i) #第二种方法: print(f1.__next__()) print(f1.__next__()) print(f1.__next__()) print(f1.__next__())
例子:菲波那切数列实现
class Fib: def __init__(self): self._a=1 self._b=1 def __iter__(self): return self def __next__(self): if self._a > 100: raise StopIteration('终止了') self._a,self._b=self._b,self._a + self._b return self._a f1=Fib() print(next(f1)) print(next(f1)) print(next(f1)) print(next(f1)) print(next(f1)) print(next(f1)) print('==================================') for i in f1: print(i)
#
1
2
3
5
8
13
==================================
21
34
55
89
144