python 中常见的魔术方法:
1、__init__(self, item):方法
在实例化对象时自动执行,多用于对对象属性进行初始化。
2、__new__(cls,item):方法
实例化对象时自触发,在__init__ 方法之前执行,作为控制对象的生成过程,实现单例设计模式。
class Human:
__instance = None
def __init__(self, name): print('init method for {}'.format(name)) def __new__(cls, *args,**kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(Human)
return cls.__instance
3、__del__(self):方法
对象被系统回收的时候自动触发(del
不一定触发)
4、__getattr__(self, item): 方法
在访问对象的item属性的时候,如果对象和他的父类并没有这个相应的属性,方法,那么将会调用这个方法来处理。有相应的属性或方法时调用对象实例的相应属性或方法。
参数 item 代表 调用的属性或方法。
class Foo:
def __init__(self, x):
self.x = x
@property
def get_01(self):
print(111)
return self.x
def __getattr__(self, item):
# 当实例对象的的 f.a属性不存再时执行的操作
print('执行的是我')
print(item)
return self.x
f1 = Foo(10)
print(f1.get_01) # 111,10
print(f1.a) # 执行的是我 , a, 10
print(f1.get_02) # 执行的是我 , get_02, 10
5.__setattr__(self, item, value): 方法
会拦截所有属性的的赋值语句。如果定义了这个方法,self.arrt = value 就会变成self,__setattr__("attr", value).这个需要注意。
当在__setattr__方法内对属性进行赋值是,不可使用self.attr = value,因为他会再次调用self,__setattr__("attr", value),则会形成无穷递归循环,
最后导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name'] = value.
class Student:
def __init__(self,item):
self.x=item
def __getattr__(self, item):
return item + ' is not exits'
def __setattr__(self, key, value):
print("执行我")
self.__dict__[key] = value+2
s = Student(10) # # 调用__setattr__ 方法 执行我
print(s.x) # 12
print(s.name) # 调用__getattr__方法 输出'name is not exits'
s.age = 1 # 调用__setattr__ 方法
print(s.age) # 输出 3
6、__getattribute__(self,item):方法
访问成员属性时自动触发,无论成员属性是否存在
lass Human:
def __init__(self): self.name = 'Python' self.sex = 'male' self.age = 18 def __getattribute__(self, item): print('getattribute call by %s' % self) # return self.name 如果返回的是self.name,则会报错 return super().__getattribute__(item) def eat(self): print('eat method is running') human = Human() print(human.name) >>>>>>>>getattribute call by <__main__.Human object at 0x000001D633849240> >>>>>>>>Python
7、__delattr__(sefl,item):方法
删除对象时自动执行,可以在删除对象时做一些其他工作
class Human:
def __init__(self): self.name = 'Python' self.sex = 'male' def __delattr__(self, item): if item == 'name': # 当删除的对象成员名称为name时,不执行删除操作,即限制了删除name成员 pass else: # del self.sex 如果执行此行,则会报错,递归数过大 return super().__delattr__(item) def eat(self): print('eat method is running') human = Human() del human.name # 不会删除name属性 del human.sex # 会删除sex属性 print(human.name) print(human.sex) >>>>Python >>>>AttributeError: 'Human' object has no attribute 'sex'
8、__str__(self): 方法 打印实例对象时 自动被调用
class Student:
def __init__(self,item):
self.x=item
def __str__(self):
print("打印对象时调用")
return "111"
s=Student(10)
print(s) # 打印对象时调用 111
9、__len__(self):方法
使用 len检测对象的长度时自动触发
class Human:
def __init__(self, name): self.name = name def __len__(self): # 必须有返回值,而且必须是整形 return len(self.name) human = Human('chengjie') print(len(human)) #如果没有实现__len__, 则无法直接使用len(human), 否则报TypeError: object of type 'Human' has no len(), 实现了__len__后,可以根据需要 >>>>8
10、__call__(self,*args,**kwargs):方法
实例化对象当做函数调用时自动触发。
class MakeCake:
def buy_yuan_liao(self): print('购买原料') def huo_mian(self): print('和面') def __call__(self, *args, **kwargs): self.buy_yuan_liao() self.huo_mian() print('蛋糕制作完成') maek_cake = MakeCake() # 实例化一个类MakeCake的对象make_cake maek_cake() # 把对象make_cake当做一个函数调用 >>>>购买原料 和面 蛋糕制作完成