Python3.x基础学习-类--__del__()、__call__()、__repr__()、__new__()、__hash__()方法
__del__()
销毁魔术方法
触发时机:当一个对象在内存中被销毁的时候自动执行
参数:至少有一个 self,
接收对象 返回值:无
作用:在对象销毁的时候做一些操作
注意:程序自动调用此方法,不需要我们手动调用。
class Cat: def __init__(self,name): print("--init--") self.name = name def __str__(self): print("--str--") return self.name def __del__(self): print("这是del方法") #对象一旦被销毁,自动触发此方法 cat1 = Cat("Tom") print(cat1) print("最后一行代码") # --init-- # --str-- # Tom # 最后一行代码 # 这是del方法
class Cat: def __del__(self): print('----del-----') def func(): cat = Cat() return cat #即使有返回值,但函数外部没有变量接受,出了函数对象依然会被销毁 ret =func() print("最后一行代码") # 最后一行代码 # ----del-----
__call__()
方法__call__():可以让类的实例具有类似于函数的行为,进一步模糊了函数和对象之间的概念
使用方式:对象后面加括号,触发执行。即:对象()或者 类()()
class Cat: def eat(self): print("吃猫粮") def __call__(self, *args, **kwargs): print("--call方法--") cat = Cat() cat.eat() cat() Cat()() # 吃猫粮 # --call方法-- # --call方法-- #__call__方法实现斐波那契 1,1,2,3,5,添加到列表中 class Fib: def __call__(self, n): self.list = [] a = 1 b = 1 for i in range(1,n+1): self.list.append(a) a,b = b,a+b return self.list fib =Fib() print(fib(5)) def fib1(n): x=[] if n==1 or n==2: return 1 return fib1(n-2)+fib1(n-1) print(fib1(5)) print(fib1(4)) # [1, 1, 2, 3, 5] # 5 # 3
__repr__()
__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): return 'name:%s--age:%d'%(self.name,self.age) per = Person('johnson',18) print(per) string ='zhou' print("大家好,我叫%s"%string) print("大家好,我叫%r"%string) # %s 默认调用str方法,%r默认调用repr方法 print("大家好,我叫%r"%per) print("大家好,我叫%s"%per) # {'name': 'johnson', 'age': 18} # 大家好,我叫zhou # 大家好,我叫'zhou' # 大家好,我叫name:johnson--age:18 # 大家好,我叫{'name': 'johnson', 'age': 18}
__new__()方法
触发机制:在实例化对时触发
参数:至少一个cls接收当前类
返回值:必须返回一个对象实例 作用:实例化对象
注意:实例化对象 Object 类底层实现,其他类继承了Object的__new__才能够实例化对象
没事别碰这个魔术方法,先触发__new__()才触发__init__
class Cat: def __init__(self): print('--init--') def __new__(cls, *args, **kwargs): print('---new---') return object.__new__(cls) #成功创建了对象,但一出函数对象就被销毁 def __del__(self): print('--del--') def __str__(self): return '--str--' def func(): cat = Cat() print(cat) return cat ret = func() print('最后一行代码------') # ---new--- # --init-- # --str-- # 最后一行代码------ # --del--
class Shopping: __instance = None def __new__(cls, *args, **kwargs): if cls.__instance==None: cls.__instance = object.__new__(cls) return cls.__instance else: return cls.__instance shop1 = Shopping() shop2 = Shopping() print(id(shop1),id(shop2)) print(shop1,shop2) shop3 = Shopping() print(id(shop3)) # 1395248497888 1395248497888 # <__main__.Shopping object at 0x00000144DB4A84E0> <__main__.Shopping object at 0x00000144DB4A84E0> # 1395248497888
__hash__()
哈希(hash)也翻译叫散列。hash算法,是将一个不定长的输入,通过hash函数变换成一个定长的输出,即哈希值
在python中,有内置的哈希函数hash(),返回一个对象(数字、字符串,不能直接用于list,set,dict)的哈希值
set1 ={1,2,3} dic = {'a':1} # print({[1]:1}) # TypeError: unhashable type: 'list' string = 'a' print(hash(string)) print(hash((1,3))) # 8878686175204649982 # 3713081631933328131
1.自定义对象能不能添加到集合中呢? 能默认调用父类的__hash__和 __eq__
2.object的hash值是怎么算的呢? id是hash的16倍
3.自定义对象添加到集合中,一般认为两个对象的属性值相同就是同一个对象 --自定义计算规则
4.注意:如果只定义了__eq__方法,没有定义__hash__方法,__hash__方法会隐式设置成None
class Person: def __init__(self,num): self.num = num p1 =Person(1) p2 =Person(2) p3 =Person(3) list =[p1,p2,p3] set(list) print(id(p1)) print(hash(p1)) # 2424376266626597764 # 3713081631933328131 # 2187348381144 # -9223371900145501987
class Person: def __init__(self,name,age): self.name = name self.age = age def __eq__(self,other): print("%s调用了eq方法"%self.name,self.age) return self.__dict__==other.__dict__ def __hash__(self): print("%s调用了hash方法"%self.name) return hash(self.name) p1 = Person('johnson',18) p2 = Person("may",11) p3 = Person('johnson',18) print(id(p1),id(p2),id(p3)) set1 = {p1,p2,p3} print(p1==p3) # 2744803718088 2744803718032 2744803717976 # johnson调用了hash方法 # may调用了hash方法 # johnson调用了hash方法 # johnson调用了eq方法 18 # johnson调用了eq方法 18 # True
https://www.cnblogs.com/kadycui/p/11838590.html
Python的__hash__函数和__eq__函数
可哈希的集合(hashed collections),需要集合的元素实现了__eq__和__hash__,而这两个方法可以作一个形象的比喻:
哈希集合就是很多个桶,但每个桶里面只能放一个球。
__hash__函数的作用就是找到桶的位置,到底是几号桶。
__eq__函数的作用就是当桶里面已经有一个球了,但又来了一个球,它声称它也应该装进这个桶里面(__hash__函数给它说了桶的位置),双方僵持不下,那就得用__eq__函数来判断这两个球是不是相等的(equal),如果是判断是相等的,那么后来那个球就不应该放进桶里,哈希集合维持现状。
class Foo: def __init__(self, item): self.item = item def __eq__(self, other): print('使用了equal函数的对象的id',id(self)) if isinstance(other, self.__class__): return self.__dict__ == other.__dict__ else: return False def __hash__(self): print('f'+str(self.item)+'使用了hash函数') return hash(self.item) f1 = Foo(1) f2 = Foo(2) f3 = Foo(3) fset = set([f1, f2, f3]) print(fset) print() f = Foo(3) fset.add(f) print('f3的id:',id(f3)) print('f的id:',id(f)) # f1使用了hash函数 # f2使用了hash函数 # f3使用了hash函数 # {<__main__.Foo object at 0x00000245E50AA518>, <__main__.Foo object at 0x00000245E52484A8>, <__main__.Foo object at 0x00000245E5248470>} # # f3使用了hash函数 # 使用了equal函数的对象的id 2499220374640 # f3的id: 2499220374640 # f的id: 2499220376992