python 魔术方法

本文详细介绍了Python中的几个重要魔术方法,包括__del__在对象销毁时的操作,__call__让类实例具备函数行为,__repr__定制对象的字符串显示,__new__在实例化过程中的作用,以及__hash__关于哈希值的解释。通过这些魔术方法,可以更灵活地控制Python对象的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值