分类:
1.创建,初始化与销毁 __init__.__del__
类实例化调用__init__;当运行结束,.del 标识符,引用计数为0的时候调用__del__
2.hash
1.内建函数hash()调用的返回值,返回一个整数,如果定义这个方法该类的实例可hash;
2.hash是为了提供set,dict的key,hash可以冲突,冲突的时候用__eq__比较内容,实现去重
3.类一般都是可以hash,由于继承基类的属性,但是没有事项__hash__,我们认为不可以hash
4.list bytearray 内部用 __hash__ = None 实现不可以hash
classPoint:def __init__(self,x,y):
self.x=x
self.y=ydef __hash__(self): #return 就是一个元祖,想要返回对象 Point(self.x,self,y)
returnhash((self.x,self.y))def __eq__(self,other): #运算符重载 p1 == p2,判断对象是否相等,返回bool
return (self.x,self.y) ==(other.x,other.y)
# return self.x ==other.x and self.y == other.ydef __repr__(self):return 'Point.x={},Point.y={}'.format(self.x,self.y)
3.bool
1.内建函数bool(),或者对象放在逻辑表达式的位置,调用这个函数返回bool,没有定义__bool__(),就找__len__()的长度,非0为真,如果__len__()也没有定义,所有实例都返回真
classA:def __len__(self):return 100
__hash__ =NoneifA():print("real a")
bool(A)
bool(A())
4.可视化
1.__repr__内建函数repr()对一个对象获取字符串表达,调用魔术方法返回字符串表达,如果没有定义,就直接返回object的定义就式显示内存的地址信息
2.__str__,str()函数,内建函数format(),print()函数调用,需要返回对象的字符串表达,如果没有定义,就去调用__repr__方法返回字符串表达,如果__repr__也没有定义,就直接返回对象的内存地址信息
3.__bytes__,bytes()函数调用,返回一个对象的bytes表达,返回bytes对象
5.运算符重载
1.比较运算符:lt,le,eq,gt,ge,ne -->[ ,>= ,!=]
2.算数运算符:add,sub,mul,truediv,mod,floordiv,pow,divmod -->[+-*/% // ** divmod]
3.iadd,isub,imul,itruediv,imod,ifloordiv,ipow --> [+=,-=,*=,/=,%=,//=,**=]
classPoint:def __init__(self,x,y):
self.x=x
self.y=ydef __sub__(self,other):return Point(self.x-other.x,self.y-other.y)def __add__(self,other):return Point(self.x+other.x,self.y+other.y)def __repr__(self):return ''.format(self.x,self.y)
6.容器和大小
1.__len__:内建函数len(),返回对象长度,
2.__iter__:迭代容器的时候,调用,返回一个新的迭代对象(没有这个方法是instance(cart,Iterable)返回false,当for i in cart:调用__iter__)
3.__contains__:in成员运算符,没有实现就掉用__iter__方法遍历
4.__getitem__:实现self[key]访问,序列对象,key接受整数位索引,或者切片,对于set,dict,key为hashable,key不存在引发保存,索引访问
5.__setitem__:是设置值的方法,索引赋值6.__missing__:字典或其子类使用__getitem__调用时,key不存在执行该方法
classCart:def __init__(self):
self.items=[]defadd(self,value):
self.items.append(value)def __len__(self):returnlen(self.items)def __iter__(self):returniter(self.items)
#yield from self.itemsdef __getitem__(self, item):returnself.items[item]def __setitem__(self, key, value):
self.items[key]=valuedef __str__(self):returnstr(self.items)def __add__(self, other):
self.items.append(other)returnself
cart=Cart()print(cart)
cart.add(1)
cart.add(2)
cart.add(3)print(cart+4+5+6) #链式变成实现加法
print(cart.__add__(17).__add__(18)
7.可调用对象
1.Pyhon一切皆对象,函数也不例外
2.__call__:类中定义一个该方法,实例就可以像函数一样调用
3.可调用对象:定义一个类,并实例化得到其实例,将实例像函数一样调用
4.要实现类实例的函数调用可以把函数调用写在__call__()内
5.可调用对象可以实现类装饰器; 见下面例子
classPoint:def __init__(self,x,y):
self.x=x
self.y=ydef __call__(self,*args,**kwargs):return "".format(self.x,self.y)
p= Point(4,5)
p()
classAdder:def __call__(self,*args):
ret=0for x inargs:
ret+=x
self.ret=retreturnret
p=Adder()
p(10,10)
p.ret
斐波数列用可调用方式并包装成容器实现
classFib:def __init__(self):
self.item=[0,1,1]def __call__(self,num):if num
self.item.append(self.item[i-1]+self.item[i-2])returnself.itemdef __iter__(self):returniter(self.item)def __len__(self):returnlen(self.item)def __getitem__(self,key):returnself.item[key]
fib=Fib()for i infib:print(i)
len(fib)
fib[2]
classFib:def __init__(self):
self.item=[0,1,1]def __call__(self,num):#num为形参,fib()先调用call,return在调用getitem魔术方法
returnself[num]def __iter__(self):returniter(self.item)def __len__(self):returnlen(self.item)def __getitem__(self,num): #这个num为实参,后调用getitem
if num
self.item.append(self.item[i-1]+self.item[i-2])#return self.item[num]
def __str__(self):returnstr(self.item)__repr__=__str__fib=Fib()
fib(5)print(fib(5))
importtimefrom datetime importdatetimefrom functools importwraps,update_wrapperclassTimeie:"""this is Timeit"""
def __init__(self,fn):
self.fn=fn#update_wrapper(self,fn)
wraps(fn)(self) #wrapper = wraps(fn)(wrapper)
def __call__(self,x,y):
self.start=datetime.now()
ret=self.fn(x,y)
delta= (datetime.now()-self.start).total_seconds()print(delta)returnret
@Timeie#add = Timeit(add)
defadd(x,y):"""this is add"""time.sleep(2)return x+y
add(4,5)
8.上下文管理
1.当一个对象同时实现了__enter__()和__exit__()方法,它就属于上下文管理的对象
2.__enter__:进入与次相关的上下文,如果存在该方法,with语法就会把该方法返回
__enter__方法返回值就是上下文中使用的对象,with语法会把他的返回值赋值给as子句的变量
3.__exit__:退出与此对象相关的上下文;方法返回一个等效的True值,压制异常,否则继续抛出异常
4.应用场景:增强功能,资源管理,权限验证(在执行代码前,做权限验证,在__enter__中处理)
5.contextlib库,@contextlib.contextmanager ;用来装饰函数,函数必须返回生成器,只有一个yield值;增加try保证exit执行
try:
yield 5 #yield之前当作enter,之后当作exit,;yield值当作enter返回值
finally:
print('exit')
classPoint:def __init__(self):print('init')def __enter__(self):print('enter')
return selfdef __exit__(self, exc_type, exc_val, exc_tb):print('exit')
with Point() as f:#output init-->enter-->f-->exit
print('f')
实例化对象的时候,并不会调用enter,进入with语句块的时候调用_enter__方法,然后执行语句体,
最后离开with语句快的时候调用__exit__方法,如果with语句块发生异常,enter,exit照样执行,上下文管理最安全
classPoint:def __init__(self):print('init')def __enter__(self):print('enter')returnselfdef __exit__(self, exc_type, exc_val, exc_tb):print('exit')print(exc_type,exc_val,exc_tb)return0
p=Point()
with p as f:#output init-->enter-->f-->exit
raise Exception("new erroe")print('f')
importtimefrom datetime importdatetimedefadd(x,y):
time.sleep(2)return x+yclassTimeit:def __init__(self,fn):
self.fn=fn
def __enter__(self):
self.start=datetime.now()returnselfdef __exit__(self, exc_type, exc_val, exc_tb):
delta= (datetime.now()-self.start).total_seconds()print(delta)def __call__(self,x,y):returnself.fn(x,y)
p=Timeit(add)print(p) #<__main__.timeit object at>
print(Timeit(add)) #<__main__.timeit object at>
with p as f:#with Timeit(add) as f ;print-->false print(p==f) f(5,6)
9.反射:动态增加属性
1.getattr(object,name,default) 通过name返回object的属性值,当属性值不存在的时候,将使用default返回,如果没有default,抛出异常,name必须为字符串
2.setattr(object,name,value) object的属性存在,则覆盖,不存在新增
3.hasattr(object,name) 判断对象是否有这个名字的属性,name必须为字符串
classDispatcher:def __init__(self):
self.run()defcmd1(self):print('i am cmd1')defcmd2(self):print("i am cmd2")defrun(self):whileTrue:
cmd= input('please input a command').strip()if cmd == 'quit':breakgetattr(self,cmd,lambda:print('unkown{}'.format(cmd)))()
1.__getattr__():一般属性会按照继承关系找,如果找不到,就会执行__getattr__()方法,没有抛错
2.__setattr__():实例通过.设置属性,如同self.x = x 就会调用__setattr__(),属性要加到__dict__就要自己完成
3.__delattr__():可以阻止通过实例删除属性的操作,但是通过类依然可以删除属性
4.__getattribute__():实例的所有属性访问都会调用__getattribute方法,它阻止了属性的查找,该方法应该返回计算后的值,或者抛出个异常;return的值作为属性的查找结果,如果抛错,调用__getattr__表示属性没有找到
classBase:
n=0classPoint(Base):
z= 6
def __init__(self,x,y):print('init')
self.x=xprint('init2')
self.y=ydefshow(self):print(self.x,self.y)def __getattr__(self,item):
setattr(self,item,0)#getattr(self,item)产生递归#return 'missing {}'.format(item)
def __setattr__(self,key,value): #self.x 就会调用这个函数,如果不操作__dict__,就是空字典
print('setattr')print("setattr {}={}".format(key,value))
self.__dict__[key] =value#setattr(self,key,value)产生递归#getattr(self,key,value)产生递归
def __delattr__(self,item):print('can not del {}'.format(item))
p1= Point(3,4)
p1.__dict__p1.aa=100 #aa:100
p1.t #t:0
del p1.x #output can not del x
del Point.z#删除类的属性
classBase:
n=0classPoint(Base):
z= 6
def __init__(self,x,y):print('init')
self.x=x
self.y=ydef __getattr__(self,item):return 'missing{}'.format(item)def __getattribute__(self,item):#所有实例的随性都从调用这个函数开始
print('getattribute')return object.__getattribute__(self,item)
属性实例查找顺序:
实例调用__getattribute__()-->instance.__dict__-->instance.__class__.__dict__-->继承德祖先类直到object-->调用__getattr__()
10.描述器