1.__del__
销毁魔术方法
触发时机:当一个对象在内存中被销毁的时候自动执行
参数:至少有一个self,接收对象
返回值:无
作用:在对象销毁的时候做一些操作
注意:程序自动调用此方法,不需要我们手动调用。
class Person(object):
def __init__(self):
print('init了')
# 当没有对象引用的时候自动执行
def __del__(self):
print('销毁了')
person = Person()
del person # 手动删除内存中的对象
print('结束了...')
"""
对象没有被删除时---->__del__最后执行
init了
结束了...
销毁了
"""
"""
对象被删除---->现将对象销毁在执行程序下面的代码
init了
销毁了
结束了...
"""
2.__call__:
__call__():可以让类的实例具有类似于函数的行为,
进一步模糊了函数和对象之间的概念。
使用方式:
对象后面加括号,触发执行。即:对象() 或者 类()()
class Person(object):
def __call__(self, *args, **kwargs):
print('call...')
# 第一种调用方法
person = Person() # 将Person的内存地址赋值给person
person() # 内存地址
# 第二种调用方法
Person()() # 内存地址
练习:用__call__实现斐波那契数列
class Fibonacci:
def __call__(self, num):
b = [1, 1]
for i in range(num - 2):
b.append(b[-1] + b[-2])
return b
fei = Fibonacci()
print(fei(12))
3.__repr__:
__repr__():改变对象的字符串显示
- 此方法是__str__()的备胎,如果找不到__str__()就会找__repr__()方法。
- %r 默认调用的是 __repr()方法,如果是字符串会默认加上 ''
-repr()方法默认调用__repr__()方法
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return '啊哈哈'
def __repr__(self):
return 'name:%s , age:%s' % (self.name, self.age)
# 没有找不到__str__时,就会调用__repr__方法
xiaoming = Person('小明', 14)
print(xiaoming)
# repr()默认使用__repr__方法
print(repr(xiaoming))
4.__new__:
实例化魔术方法
触发时机: 在实例化对时触发
参数:至少一个cls 接收当前类
返回值:必须返回一个对象实例
作用:实例化对象
注意:实例化对象是Object类底层实现,其他类继承了Object的__new__才能够实现实例化对象。
class Person(object):
# 初始化
def __init__(self):
print('----init----')
# 实例化方法---->创建对象
def __new__(cls, *args, **kwargs):
print('-----new------')
return super().__new__(cls) # 调用父类的__new__()方法创建对象,最后返回给person
# None说明我们没有创建对象,调用父类的__new__方法就可以创建对象了
person = Person()
print(person)
没事别碰这个魔术方法,先触发__new__才会触发__init__
5.Python中的比较is和 ==
is 比较两个对象的 id 值是否相等,是否指向同一个内存地址;
== 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了。
默认会调用对象的 __eq__()方法。继承自 object 的 __eq__ 方法比较两个对象的id
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
return self.__dict__ == other.__dict__
person = Person('ZS', 12)
person1 = Person('ZS', 12)
print(person == person1) # True 对于自定义对象,一般我们认为值相同,就是同一个对象。所以我们要复写__eq__方法
print(person is person1) # False
lst = []
lst.append(person)
if person1 not in lst:
lst.append(person1)
print(lst) # [<__main__.Person object at 0x000000000077DA20>]
5.__hash__(哈希):
不可哈希类型:字典、列表
可哈希类型:字符串、集合(集合内不能存在字典、列表)
1.自定义对象能不能添加到集合中呢?能默认调用父类的__hash__和__eq__
2.object的 hash 值是怎么算的呢,id 是hash 的16倍
3.自定义对象添加到集合中,一般认为两个对象的属性值相同就是同一个对象
--自定义计算规则。
4.注意,如果只定义了__eq__方法,没有定义__hash__方法,__hash__方法会隐式设置成None
在自定义类中,如果没有实现__eq__()和__hash__()方法,会继承object的__eq__()方法和__hash__()方法。
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other): # 比较内容
return self.__dict__ == other.__dict__
def __hash__(self):#哈希比较的是id
return hash(self.name) + hash(self.age)
# 集合自动去重
# 先根据__hash__进行快速查询,有没有对象的hash值和我相同
per1 = Person('zs', 18)
per2 = Person('zs', 18)
set1 = {per1, per2}
print(set1)
# object.__hash__()返回的值是id()的1/16
print(id(per1) / hash(per1))