Python高级 - 魔术方法

__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函数就会报错
17 # 要求obj必须实现了__len__,要求这个方法的返回值必须是数字int类型

 

__new__

 1 # __new__  # 构造方法 : 在实例化的过程中,最先执行的方法,在执行init之前,用来创建一个对象
 2 # __init__ # 初始化方法 : 在实例化的过程中,在new执行之后,自动触发的一个初始化方法
 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__

 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__方法
17 # str(obj),要求必须实现了__str__,要求这个方法的返回值必须是字符串str类型

__repr__

 1 # __str__ : str(obj),要求必须实现__str__,要求这个方法的返回值必须是字符串str类型
 2             # print %s str
 3 # __repr__ : 是__str__备胎.如果有__str__方法,那么# print %s str都先去执行__str__方法,并且使用str的返回值
 4 #            如果没有__str__,那么print %s str都会执行__repr__
 5             # repr(obj), %r
 6 # 如果子类没有__str__, 先找父类(除object)的__str__,没有再找子类的__repr__(备胎)
 7 class A:
 8     def __repr__(self):
 9         return "A repr"
10 
11     def __str__(self):
12         return "A str"
13 
14 class B(A):
15     def __init__(self, name):
16         self.name = name
17 
18     def __repr__(self):
19         return "B repr"
20 
21     # def __str__(self):
22     #     return "B str"
23 
24 a = B("alex")
25 print(str(a), repr(a))
26 print("%s | %r" % (a, a))

 

总结:

__call__  相当于 obj()
__len__ 相当于 len(obj)
__new__ 特别重要, 开辟内存空间,类的构造方法
__str__ str(obj)、print(obj)、'%s' % obj
__repr__ repr(obj)'%r' % obj还是__str__的备胎
__repr__ 在继承中父类__str__优先级高于子类(备胎)__repr__

所有的双下方法,都没有 需要在外部直接调用的
而是总有一些其他的 内置函数 特殊的语法 来自动触发这些 双下方法

set集合的去重机制:先调用hash,再调用eq,eq不是每次都会触发,只有hash值相等的时候才会触发

hash(obj) # obj内部必须实现了__hash__方法

hash对同一个值在同一次执行python代码的时候hash值永远不变
对同一个值在多次执行python代码的时候hash值是不同的


hash的结果找到一块内存地址,只要这快地址没有数据,就说明之前没有重复的数据
如果这款地址上有数据存在了才判断这个值和要存储的值是否一样
如果一样覆盖去重
如果不一样,二次寻址给这个值换个地址存储




posted @ 2019-09-15 00:23  arley520  阅读(176)  评论(0编辑  收藏  举报