魔术方法:就是类中的方法(预定义的方法),在某个特定的时机会被自动的调用。
1、__del__():销毁对象时,被自动的调用
1 class Person:
2 def __init__(self, name):
3 self.name = name
4 print('%s 被初始化' % self.name)
5
6 def __del__(self):
7 print("%s 被删除 " % self.name)
8
9
10 p1 = Person("奶茶")
11 p2 = Person("蛋糕")
12
13 print('xixi')
14 del p1
15 print('haha')
16
17 # 奶茶 被初始化
18 # 蛋糕 被初始化
19 # xixi
20 # 奶茶 被删除
21 # haha
22 # 蛋糕 被删除
2、__call__():
功能:让类的实例具有类似有函数(方法)的功能。让对象可以被调用, 调用时执行的就是__call__中的函数体
触发时机:调用对象的时候——对象()
1 class Person:
2 def __init__(self, name, sex, age, sister=None, brother=None):
3 self.name = name
4 self.sex = sex
5 self.age = age
6 self.sister = sister
7 self.brother = brother
8
9 def __call__(self): # 获取....
10 if self.sex == "boy":
11 print(self.sister)
12 else:
13 print(self.brother)
14
15 def get_age(self):
16 print(self.age)
17
18
19 p1 = Person("xixi", "boy", 18, "haha")
20 print(p1.name) # xixi
21 p1.get_age() # 18
22 p1() # haha
3、__repr__():print(对象) 打印对象时会被调用
__str__():print(对象) 打印对象时会被调用
print(对象)默认情况下打印结果是,对象的内存地址
重写__str__()方法,返回什么,print(对象)打印的结果就是什么
区别与联系:
1、TypeError:__repr__ returned non-string (type NoneType)
以上两个函数都必须有返回值,且返回值类型为str类型;
2、打印对象时, 如果使用%s占位符, 默认调用的是__str__()方法
如果使用%r占位符, 默认调用的是__repr__()方法
3、有repr, 没有str时,%s、%r 都可调用repr方法;
没有repr, 有str时, %s 调用的是str的方法,%r 打印的是对象的地址(默认的)
4、print(repr(对象)) 默认调用__repr__()方法
print(str(对象)) 默认调用__str__()方法
1 class Person:
2 def __init__(self, name):
3 self.name = name
4
5 def __str__(self):
6 return "我是str"
7
8 def __repr__(self):
9 return "我是repr"
10
11
12 p1 = Person("xixi")
13 # repr&str方法都没有
14 # print(p1) # <__main__.Person object at 0x000000000214D198>
15
16 # repr&str方法都有
17 # print("%s" % p1) # 我是str
18 # print("%r" % p1) # 我是repr
19
20 # 只有repr方法:
21 # print("%s" % p1) # 我是repr
22 # print("%r" % p1) # 我是repr
23
24 # 只有str方法
25 # print("%s" % p1) # 我是str
26 # print("%r" % p1) # <__main__.Person object at 0x00000000026BD198>
27
28 print(repr(p1))
29 print(str(p1))
4、__new__(cls):类方法
功能:实例化一个对象
触发时机:当实例化对象的时候,会被自动调用
返回值:实例化的那个对象;
__new__(cls)方法将实例化的对象传递给__init__(self)方法的第一个参数;
__new__()是object类底层的实现——单例
1 class Person:
2 def __new__(cls, *args, **kwargs): # 必须有返回值: 创建好的对象,类的实例
3 print("我是new")
4 return super().__new__(cls)
5
6 def __init__(self):
7 print("我是init")
8
9
10 p = Person() # 创建对象
11 # 我是new
12 # 我是init
13 print(p) # <__main__.Person object at 0x0000000001EA8358>
5、__eq__:
只要俩对象的属性值都相等, 我们就认为这俩对象相等
通过__eq__()方法去实现,必须有返回值bool用来代表是否相等
使用__eq__()方法定义比较的规则,对象进行比较时需要使用 == 关系运算符进行比较
对象.__dict__ 获取当前对象的属性, 包括私有(字典{"属性名": "属性值", ...})
(1)基础数据类型的对象
is : 比较的是对象的地址
== : 比较的是对象的内容
cmd 对于小整数 [-5, 256] 之间的数字进行了缓存,所以可以在缓存中重复使用
pycharm做了优化,他把不可变数据类型中的很大范围的数据都做了缓存,所以在缓存中可以重复使用
在pycharm中对某些即使很大的整数进行地址的比较 is 都是相等的
(2)自定义类的对象
is 和 == 比较的都是对象的地址
1 a = "12345"
2 b = "12345"
3
4 print(a == b) # True
5 print(a is b) # True
6 print(id(a)) # 4772224
7 print(id(b)) # 4772224
8
9
10 list1 = [1, 2, 3, 4]
11 list2 = [1, 2, 3, 4]
12 print(list1 == list2) # True
13 print(list1 is list2) # False
14 print(id(list1)) # 63488968
15 print(id(list2)) # 63184328
16
17
18 class Person:
19 def __init__(self, name, age):
20 self.name = name
21 self.age = age
22
23 def __eq__(self, other): # other, 另外一个要进行比较的对象
24 if self.__dict__ == other.__dict__: # 如果当前对象和被比较对象的所有属性值相等, 我们就认为这俩对象相等
25 return True
26 else:
27 return False
28
29
30 p1 = Person('xixi', 6)
31 p2 = Person('xixi', 6)
32 print(p1 == p2) # True
33 print(p1 is p2) # False
34 print(id(p1)) # 43097840
35 print(id(p2)) # 43101544
6、__hash__() : 当获取对象的哈希值时,调用该魔术方法
hash(对象)
set, list, dict 没有__hash__()方法, hash(列表对象):报错,不可被哈希
列表对象.__hash__ ——> None
如果只定义了__eq__()方法, 而没有定义__hash__(), 默认会将__hash__方法设置为None
1 # 设计二维坐标类Point判断2个坐标是否相等,
2 # 并能根据hash函数计算坐标的哈希值;
3
4 class Point:
5 def __init__(self, x, y):
6 self.x = x
7 self.y = y
8
9 def __eq__(self, other):
10 if self.x == other.x and self.y == other.y:
11 return True
12 else:
13 return False
14
15 def __hash__(self):
16 return hash((self.x, self.y))
17
18 point1 = Point(3, 4)
19 point2 = Point(3, 4)
20
21 print(point1 == point2) # True
22
23 print(hash(point1)) # 3713083796997400956
24 print(hash(point2)) # 3713083796997400956