__call__
1 # __call__ 2 class A: 3 def __call__(self, *args, **kwargs): 4 print('执行call方法') 5 6 a = A() 7 a() # 对象()相当于调用__call__方法 8 9 A()() # 类名()()相当于先实例化得到一个对象,再对对象(),调用__call__方法 10 11 class B(): 12 def __init__(self, cls): 13 self.a = cls() 14 self.a() 15 16 b = B(A)
__len__
1 # __len__ 2 内置函数(len)和类的内置方法(__len__)是有奸情的 3 class mylist(): 4 def __init__(self): 5 self.lst = [1,2,3] 6 self.name = 'alex' 7 self.age = 83 8 9 def __len__(self): 10 return len(self.__dict__) 11 12 l = mylist() 13 print(len(l)) 14 # len(obj)相当于调用了这个obj的__len__方法 15 # __len__方法return的值就是len函数的返回值 16 # 如果一个obj对象没有__len__方法,那么len函数就会报错
__new__
1 # __new__ # 构造方法 2 # __init__ # 初始化方法 3 4 class Single: 5 def __new__(cls, *args, **kwargs): 6 print("new方法") 7 return object.__new__(cls) 8 9 def __init__(self): 10 print("init方法") 11 12 # 1.开辟一个空间,属于对象的 13 # 2.把对象的空间传给self,执行init 14 # 3.把这个对象的空间返回给调用者 15 class Single: 16 def __new__(cls, *args, **kwargs): 17 obj = object.__new__(cls) 18 print("new方法", obj) 19 return obj 20 21 def __init__(self): 22 print("init方法", self) 23 24 obj = Single() 25 # single的new, single没有, 只能调用object的new方法 26 # new方法在什么时候执行? 27 # 在实例化之后,__init__之前先执行new来创建一块空间
单例类
1 # 如果一个类,从头到尾只能有一个实例,说明从头到尾只开辟了一块属于对象的空间,那么这个类就是一个单例类 2 class Single: 3 __ISINSTANCE = None 4 def __new__(cls, *args): 5 if not cls.__ISINSTANCE: 6 cls.__ISINSTANCE = object.__new__(cls) 7 return cls.__ISINSTANCE 8 9 def __init__(self, name, age): 10 self.name = name 11 self.age = age 12 13 s1 = Single("alex", 83) 14 s2 = Single("taibai", 43) 15 print(s1, s2)
__str__ / __repr__
1 class Student: 2 def __str__(self): 3 return '%s %s' % (self.name, self.school) 4 5 def __init__(self, name): 6 self.name = name 7 self.school = "oldboy" 8 9 alex = Student("alex") 10 print(alex) 11 print(str(alex)) # 内置的数据类型, 内置的类, 相当于执行__str__ 12 print('学生 : %s' % alex) 13 14 # print(obj) 相当于执行obj.__str__方法 15 # str(obj) 相当于执行obj.__str__方法 16 # '%s' 相当于执行obj.__str__方法
总结:
__call__ 相当于 obj()
__len__ 相当于 len(obj)
__new__ 特别重要, 开辟内存空间,类的构造方法
__str__ str(obj)、print(obj)、'%s' % obj
所有的双下方法,都没有 需要在外部直接调用的
而是总有一些其他的 内置函数 特殊的语法 来自动触发这些 双下方法