Python基础 面向对象常用魔术方法

一 常用的魔术方法

1.__del__

销毁魔术方法

触发时机:当一个对象在内存中被销毁的时候自动执行

参数:至少有一个self,接收对象

返回值 : 无

作用 : 在对象销毁的时候做一些操作

注意 : 程序自动调用此方法,不需要我们手动调用

练习1 : 测试__del__()方法的执行时机

class Person(object):
    def __init__(self):
        print('init...')

    def __del__(self):
        print('销毁了')

per1 = Person()
del per
per2 = Person()
print('程序结束了')
"""
init......
销毁了
程序结束了
"""

per 是一个全局变量,当程序执行完后,per变量才会从内存中消失,因此先打印‘’销毁了‘’

在打印‘程序结束了’

del关键字  是从内存中删除变量,因此先打印‘init...’ 

2  __call__ ()

__call__():可以让类的实例具有类似于函数的行为,进一步模糊了函数和对象之间的概念。

使用方式:

对象后面加括号,触发执行,即:对象()或者类()()

class Person(object):
    def __call__(self,*args,**kwargs):
        print('call...')

#调用方式
person = Person()  #将Person地址赋值给person
person()           #内存地址调用
Person()()         #内存地址调用

"""
call...
call...
"""
练习2   使用__call__方法实现斐波那契数列

class Fibonacci(object):
    def __call__(self,num):
        a,b = 1,1   #元组方式
        self.lst = []

        if num <= 2 :
            self.lst.append(a)
            self.lst.append(b)
        else:
            for i in range(1 , num + 1):
                self.lst.append(a)
                a,b = b , a + b
        return self.let

fibo = Fibonacci()
ret = fibo(8)
print(ret)

"""
[1, 1, 2, 3, 5, 8, 13, 21]
"""




3  __repr__

__repr__():改变对象字符串显示

此方法是__str__()的备胎,如果找不到__str__()就会找__repr__()的方法

--%r  默认调用的是__repr()方法,如果是字符串会默认加上' '

--  repr()方法默认调用__repr__(方法)

calss Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def __str__(self):
        msg = 'name{},age{}'.format(self.name,self.age)
        return msg

    #如果没有__str__的时候,会执行__repr__方法
    #如果有就不执行

    def __repr__(self):
        msg = 'name--->>>{},age--->>>{}'.format(self.name,self.age)
        return msg

person = Person('赵四',30)
print(person)       #name赵四,age30
#当注释掉__str__时   #name--->>>赵四,age--->>>30

print('%s' % person)   #name赵四,age30
print('%s' % person)   #name---->>赵四,age---->>30

print(repr(person))    #name---->>赵四,age---->>30


4 __new__()方法

实例化魔术方法

触发时机:在实例化对象时触发

参数:至少一个cls 接受当前类

返回值 : 必须返回一个对象实例

作用:实例对象化

注意:实例对象化是object类底层实现,其他类继承了object的__new__才能够实现实例化对象

PS : 没事别碰这个魔术方法,先触发__new__才会触发__init__

class Person(object):
    def __init__(self):
        print('init...')

#实例化方法(构造方法)————>>先创建对象,在初始化 所以先执行__new__,再执行__init__

    def __new__(cls,*args,**kwargs):
        print('new...')
        ret = super().__new__(cls)   #调用父类中的__new__方法  创建对象
        #接受返回值
        return ret

person = Person()
print(person)

"""
new...
init...
<__main__.Person object at 0x0000000001170EB8>
"""

5 python中的比较 is 和 ==

is 比较两个对象的 id 值是否相等,是否指向同一个内存地址;

== 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了。

默认会调用对象的 __eq__()方法。继承自 object 的 __eq__ 方法比较两个对象的id

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        return self.__dict__ == other.__dict__   #判断值是否相等

per1 = Person('zs',10)
per2 = Person('zs',10)
print(per1.__dict__)   #{'age': 10, 'name': 'zs'}
# per2 = per1
print(per1 == per2)     #True
print(per1 is per2)     #False
class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

    # def __eq__(self, other):
    #     print('xxx')

    def __eq__(self,other):
        return self.__dict__ == other.__dict__

per1 =   Person('zs',12)
per2 =   Person('ks',24)
per3 =   Person('ww',36)
# print(id(per1))     #12062560
# print(id(per2))     #12062616
# print(id(per3))     #12062672

#1对象值不同进行比较
print(per1 is per2)    #False
print(per1 == per2)    #False   值不相同
#2 对象值相同进行比较
print(per1 is per3)    #False
print(per1 is per3)    #False 值不相同为什么还是False呢?
                        #  而list中的 ==  就相同了呢
# == 默认调用的是对象的__eq__()方法。object.__eq__()方法
#默认比较的是两个对象的地址
per3 = per1

6 __hash__

哈希(hash)也翻译做散列。Hash算法,是将一个不定长的输入,用过哈希函数换成一个定长的输出,即哈希值

这种哈希变换也是一种单向运算,具有不可逆性即不能根据哈希值还原出输入消息。常见的hash算法有:SM3  MD5  SHA-等等

hash主要应用在数据结构和密码数学领域

在不同的应用场景下,hash函数的选择也会有所侧重。比如在管理数据结构时,主要要考虑运算的快速性

在python中有内置的哈希函数hash(),返回一个对象(数字  字符串   不能直接用于list  set  dictionary)的哈希值,示例代码如下

s = 'a'
ret = hash(s)
print(ret)
#840845198308593275 

在python中set集合要求数据类型是可哈希的,因为set 集合会默认调用的__hash__函数进行快速查询时,如果找到了则调用对象__eq__判断两个是否相同

如果相同则不添加。保证数据的唯一性(自动去重功能)

dict 数据结构类型的key必须是可哈希的,因为dict是无序的,因此通过key的hash算法来快速查询,节约时间

不可哈希数据类型 内部__hash__直接等于了None set集合无法通过内置的__hash__来算出哈希值,因此不能存放

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        msg = 'name{},age{}'.format(self.name, self.age)
        return msg

per1 = Person('zs',10)
per2 = Person('kh',30)
per3 = Person('ww',60)

set  = {per1,per2,per3 }
print(set)
#默认 object 中的__hash__()算出来的值,是id值得1/16
print(id(per1)/hash(per1))

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # def __str__(self):
    #     msg = 'name{},age{}'.format(self.name, self.age)
    #     return msg

    # 在向集合添加元素时,要判断哈希值  和属性值  所以要福复写一下两个方法
    def __eq__(self, other):
        return self.__dict__ == other.__dict__


    def __hash__(self):
        return hash(self.name)+hash(self.age)

per1 = Person('zs',10)
per2 = Person('kh',10)
集合去重原理 :先根据哈希值快速查找,又没有一个对象的哈希值和我的相同,
再比较属性值是否相同,所以要用__eq__()比较属性值
__hash__()--->>hash值 --->>> id 值
id不同  hash就不同
需求  只要是对象的属性值相同,就认为是同一个对象,就不让添加


print(per1)
print(per2)
set = {per1}
set.add(per2)
print(set)

自定义对象添加到集合中,我们一般认为两个对象的属性值相同就是同一个对象。因此需要我们手动复写__eq__方法和__hash__方法。

注意,如果只定义了__eq__方法,没有定义__hash__方法,__hash__方法会隐式设置成None

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值