魔术方法

常用魔术方法

1、__ del __( )方法

销毁魔术方法
触发时机:当一个对象在内存中被销毁的时候自动执行
参数:至少有一个self,接收对象
返回值:无
作用:在对象销毁的时候做一些操作
注意:程序自动调用此方法,不需要我们手动调用。

2、__ call __( )方法

可以让类的实例具有类似于函数的行为,进一步模糊了函数和对象之间的概念。
使用方式
对象后面加括号,触发执行。
即:对象()或者 类()()

class Person():
    def eat(self):
        print('xxx')
    def __call__(self, *args, **kwargs):
        print('zzz')

person = Person()
person()
print('程序结束了')

3、__ repr __( )方法

改变对象的字符串显示
此方法是__ str__()的备胎。如果找不到__str__()就会找__repr__()方法。
%r 默认调用的是 __ repr__()方法,如果是字符串会默认加上 ’ ’
repr()方法 默认调用__repr__()方法

class Person():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    # def __str__(self):
    #     return str(self.__dict__)
    def __repr__(self):
        s = 'name:%s age:%s'%(self.name,self.age)
        return s

per = Person('zs',13)
print(per)
# 有__str__()方法就会调用__str__()方法
# 如果没有__str__()方法就会调用__repr__()方法
# %r 调用字符串 默认 给字符串加 ''
# text = 'I am 22 years old.'
# print('I said:%s.'%text)
# print('I said:%r'%text)
# %r 默认调用__repr__()
print('I said:%r.'%per) # 调用__repr__()
# print('I said:%s'%per) # 调用__str__()
# repr() 默认调用__repr__()方法。
print(repr(per))

4、__ new __( )方法 (重点)

实例化魔术方法
触发时机:在实例化对象时触发
参数:至少一个cls接收当前类
返回值:必须返回一个对象实例
作用:实例化对象
注意:实例化对象是Object类底层实现,其他类继承了Object的__new__才能够实现实例化对象。
没事别碰这个魔术方法
先触发__new__才会触发__init__

练习1:查看__new__方法的执行时机
class Dog():
    def __new__(cls, *args, **kwargs):
        print('----__new__----')
    def __init__(self):
        print('__init__')
    def __del__(self):
        print('__del__')

# 1.只复写__new__()方法
dog = Dog()
print(dog) # None 说明没有创建对象,刚才不是说它负责创建对象吗
# 因为我们重写了__new__方法,只是打印没有实现创建对象的功能
# 调用父类的__new__方法就可以创建对象了
'''
打印结果:
----__new__----
None
'''
# 练习2:调用父类的__new__方法,创建当前对象。
class Dog():
    def __new__(cls, *args, **kwargs):
        print('----__new__----')
        new__ = object.__new__(cls)
        return new__
# 创建对象
dog1 = Dog()
print(dog1)
'''
打印结果:
----__new__----
None
'''

5、__ str __( )方法

触发时机:使用print(对象)或者str(对象)的时候触发
参数:一个self接收对象
返回值:必须是字符串类型
作用:print(对象)时,进行操作,得到字符串,通常用于快捷操作
在Python中 使用print()函数输出对象名称的时候默认情况下,会打印对象名引用的内存地址,
如果希望打印对象的属性值,可以使用__str__(self)这个方法。

# 创建Cat类,向控制台打印cat对象的name和age的值。
class Cat():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '姓名:{},年龄:{}'.format(self.name,self.age)

cat = Cat('tom',10)
print(cat) # 姓名:tom,年龄:10

6、is和==区别

is 比较两个对象的id值是否相等,是否指向同一个内存地址;
== 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了。
默认会调用对象的__eq__()方法。继承自object的__eq__()方法比较两个对象的id

# 1.a和b的地址相同
a = ['I','love','python']
b = a # 将a的地址赋值给b
print(a,id(a))
print(b,id(b))
print(a is b)
print(a == b)
# 2.a和b的地址不同
a = ['I','love','python']
b = ['I','love','python']
print(a,id(a))
print(b,id(b))
print(a is b)
print(a == b)
class Person():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    # def __eq__(self, other):
    #     return self.__dict__ == other.__dict__

per1 = Person('zs',12)
per2 = Person('zs',13)
per3 = Person('zs',12)
print(id(per1))
print(id(per2))
print(id(per3))
# 1.对象值不同进行比较
print(per1 is per2) # False
print(per1 == per2) # False 值不相同
# 2.对象值相同进行比较
print(per1 is per3) # False
print(per1 == per3) # False 值相同为什么是False呢?而list中的==就相同了呢。
# 默认调用的是对象的__eq__()方法
# object.__eq__()方法 默认比较的是两个对象的地址
per3 = per1 # 把per1的地址赋值给per3
print(per3==per1) # True,为什么
# 3.对于自定义对象一般我们认为对象的值相同就是同一个对象。因此需要复写__eq__()方法
print(per1 == per3) # True
# 练习:在实际应用中,有一个场景是处理对象是否在list里,不在就加入。
# 注意:list的in操作就是通过==来判断是否在list中。
lst1 = []
lst1.append(per1)
print(lst1) # [<__main__.Person object at 0x0000000002149748>]
if per3 not in lst1:
    lst1.append(per3)
print(lst1) # [<__main__.Person object at 0x0000000002149748>]
# per1 和 per3的值相同,所以我们认为per1和per3是同一个对象,所以per3(即per1)在列表中,所以if条件不满足,lst1中只有一个元素

注意:
因为python缓存并复用了小的整数和小的字符串,对象42也许并不像我们所说的被回收;
相反地,它将可能仍被保存一个系统表中,等待下次你的代码生成42来重复利用。
尽管这样,大多数种类的对象都会在不再引用时马上回收,对那些不会被回收的,缓存机制与代码并没有什么关系。

a = 42
b = 42
print(a is b) # True
print(a == b) # True

7、__ hash __( )方法

哈希(hash)也翻译作散列。Hash算法,是将一个不定长的输入,通过哈希函数变换成一个定长的输出,即哈希值。
这种哈希变换是一种单向运算,具有不可逆性即不能根据哈希值还原出输入信息。常见的Hash算法有:SM3、MD5、SHA-1等。
Hash主要应用在数据结构以及密码学领域。
在不同的应用场景下,hash函数的选择也会有所侧重。比如在管理数据结构时,主要考虑运算的快速性。
在python中有内置函数hash(),返回一个对象(数字、字符串,不能直接用于list、set、dictionart)的哈希值。
在python中set集合要求数据类型是可哈希的,因为set集合会默认调用对象的__hash__函数进行快速查询,如果找到了则调用对象的__eq__判断两个是否相同,如果相同则不添加。
保证数据的唯一性(自动去重功能)
dict数据结构的key必须是可哈希的,因为dict是无序的因此通过key的hash算法来快速查询,节约时间。

set1 = {'a','b',[1,2,3]}
print(set1) # 报错,[1,2,3]列表时不可哈希的。
class Person():
    def __init__(self,num):
        self.num = num

p1 = Person(1)
p2 = Person(2)
p3 = Person(3)
lst = [p1,p2,p3]
set1 = set(lst)
print(set1)
# hash()函数默认调用object类的__hash__()方法。
# 默认object.__hash__()方法的哈希值是 id值/16
print(id(p1)/16) # 180781786495.0
print(hash(p1))  # 180781786495 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值