Python基础 面向对象常用魔术方法
一 常用的魔术方法
1.__del__
销毁魔术方法
触发时机:当一个对象在内存中被销毁的时候自动执行
参数:至少有一个self,接收对象
返回值 : 无
作用 : 在对象销毁的时候做一些操作
注意 : 程序自动调用此方法,不需要我们手动调用
练习1 : 测试__del__()方法的执行时机
[code]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__():可以让类的实例具有类似于函数的行为,进一步模糊了函数和对象之间的概念。
使用方式:
对象后面加括号,触发执行,即:对象()或者类()()
[code]class Person(object): def __call__(self,*args,**kwargs): print('call...') #调用方式 person = Person() #将Person地址赋值给person person() #内存地址调用 Person()() #内存地址调用 """ call... call... """
[code]练习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__(方法)
[code]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__
[code]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
[code]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
[code]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)的哈希值,示例代码如下
[code]s = 'a' ret = hash(s) print(ret) #840845198308593275
在python中set集合要求数据类型是可哈希的,因为set 集合会默认调用的__hash__函数进行快速查询时,如果找到了则调用对象__eq__判断两个是否相同
如果相同则不添加。保证数据的唯一性(自动去重功能)
dict 数据结构类型的key必须是可哈希的,因为dict是无序的,因此通过key的hash算法来快速查询,节约时间
不可哈希数据类型 内部__hash__直接等于了None set集合无法通过内置的__hash__来算出哈希值,因此不能存放
[code]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))
[code] 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
- Python 面向对象常用魔术方法
- Java面向对象基础--String类中常用的方法
- php面向对象基础概念(属性重载的魔术方法)__get(),__set(),__isset(),__unset()
- javascript 面向对象基础(三)面向对象的常用属性和方法
- 面向对象基础续1(String类、String类的常用方法、this关键字)
- PHP面向对象中常用的魔术方法总结
- 详谈PHP面向对象中常用的关键字和魔术方法
- php学习笔记------[php面向对象中常用关键字与魔术方法]
- (40)面向对象的三大特性继承性(41)面向对象中常用的关键字和魔术方法
- php学习笔记------[php面向对象中常用关键字与魔术方法]
- PHP面向对象中常用关键字和魔术方法
- python面向对象开发3 (内部类-构造-析构)魔术方法)
- 面向对象中的常用魔术方法
- php面向对象魔术方法介绍
- Php面向对象魔术方法总结
- php面向对象魔术方法
- 面向对象--魔术方法
- JS面向对象组件(三)--面向对象中的常用属性和方法
- Objective-C中数组对象排序的方法(OC中NSString的常用API的基础应用2)
- python DB-API数据库常用对象及方法,postgresql为例