类方法--双下方法:与内置函数有千丝万缕的关系
一、改变对象的字符串显示__str__,__repr__
obj.__str__ 类似str(obj)
obj.__repr__ 类似repr(obj)
def __init__(self,name): self.name=name def __str__(self): return '她是%s'%self.name # str 执行的必须是字符串形式 def __repr__(self): return str(self.__dict__) # repr执行的必须是字符串形式 teacher=Person('teacher')
#第一种调用方法 print(teacher) #她是teacher 打印一个对象的时候,就是调用a.__str__ print(repr(teacher)) #{'name': 'teacher'} 调用a.__repr__ #第二种调用方法 print('%s'%teacher) #她是teacher 相当于执行了双下str方法 print('%r'%teacher) #{'name': 'teacher'} 相当于执行了双下repr方法 #第三种调用方法 print(str(teacher)) #她是teacher 相当于触发了__str__方法 print(repr(teacher)) #{'name': 'teacher'} 相当于触发了__repr__方法

class B: def __str__(self): return 'str : class B' def __repr__(self): return 'repr : class B' b=B() print('%s'%b) #str : class B print('%r'%b) #repr : class B
""" object 里有一个__str__内置方法,一旦被调用,就返回调用这个方法对象的内存地址 打印一个对象的时候,就是调用a.__str__ # %s str() 直接打印 实际上都是走的__str__ # %r repr() 实际上都是走的__repr__ print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。 repr(),只会找__repr__,如果没有找父类的 """
class Person: def __init__(self,name): self.name=name def __repr__(self): return str(self.__dict__) teacher=Person('teacher') print(teacher) #{'name': 'teacher'} 这时候没有双下str, 会执行repr方法,
#注释:repr 是str的备胎,但str不能做repr的备胎 #备胎顺序:当类没有继承其他;类,直接继承object祖类则 备胎顺序是:自己的str--->自己的repr--->祖类的str--->祖类的repr # 当类继承的有其他类的话顺序是:自己的str--->继承类的str--->自己的repr--->继承类的repr--->祖类的str--->祖类的repr
二、析构方法,当对象在内存中被释放时,自动触发执行。
__del__ del 对象 就触发了
class A: def __del__(self): print('执行我啦') a=A() del a #先触发执行了__del__,再删除了a print(a) #删除后再打印会报错
__del__
析构函数: 在删除一个对象之前进行一些收尾工作
class B: def __del__(self): self.f.close() b=B() b.f=open('uerseinfo',mode='w',encoding='utf-8') b.f.write('zxc') #在文件里写入了zxc del b #b.f 拿到了文件操作符消失在了内存中
三、__call__ 对象后面加括号,触发执行。*****
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;
而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class C: def __init__(self,name): self.name=name def __call__(self): for k in self.__dict__: print(k+':',self.__dict__[k]) c = C('zxc') a=C('zxc')() #name: zxc c() #name: zxc
__len__ len()触发执行__len__
class A: def __init__(self,name,love): self.dog= name self.zxc= love def __len__(self): return len(self.__dict__) a = A('zxc','pig') b=A('zxc','dog') print(a.__dict__) #{'zxc': 'pig', 'dog': 'zxc'} print(len(a.__dict__)) #2
__eq__
class D: def __init__(self,name,love): self.name= name self.love= love def __eq__(self, other): if self.name==other.name: return True else: return False a=D('zxc','pig') b=D('zxc','dog') print(a==b) #True
__hash__
class A: def __init__(self,name,sex): self.name = name self.sex = sex def __hash__(self): return hash(self.name+self.sex) a = A('egon','男') b = A('egon','nv') print(hash(a)) #-211948449 print(hash(b)) #959576532
__new__ ******
__new__执行先于__init__中的内容 ,并且在实例化的时候自动执行
class New: def __init__(self,name): self.name=name print('in init funcing') def __new__(cls, *args, **kwargs): print( 'in new funcing') return object.__new__( New) a1=New('zxc') #in new funcing 最先打印的是__new__方法.再打印in init funcing print(a1) #<__main__.New object at 0x01D4EAD0> print(a1.name) #zxc
__new__进阶:23种设计模式中很简单的一个:单例模式,核心思想就是__new__
单例模式特点:
""" 一个类 始终 只有 一个 实例 当你第一次实例化这个类的时候 就创建一个实例化的对象 当你之后再来实例化的时候 就用之前创建的对象 """
#注释:一旦有任何修改,都会还是对原来的那个进行重新赋值,并且覆盖之前的实例,从始至终只有一个实例

class New: __flag=False def __init__(self,name,sex): self.name=name self.sex=sex def __new__(cls, *args, **kwargs): if cls.__flag: return cls.__flag cls.__flag=object.__new__(cls) return cls.__flag a=New('zxc',38) print(a.name) #zxc b=New('zzy',18) print(a.name) #zzy a.cloth='花裙子' print(b.cloth) #花裙子
item系列
__getitem__\__setitem__\__delitem__
class Item: def __init__(self,name,age): self.name=name self.age=age def __getitem__(self, item): if hasattr(self,item): return self.__dict__[item] else: return 1 def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): del self.__dict__[key] i=Item('zxc',38) 两种方法查,其实内部机制一样 print(i.name) # zxc print(i['name']) # zxc
两种方法改,其实内部机制一样
i['name']='zzxxcc' print(i.name) ##zzxxcc i.__dict__['name']='stupd_zxc' print(i.name) #stupd_zxc
两种方法删除,其实内部机制一样
del i['name'] print(i['name']) #1 这种查询方法,虽然找不到,但是不像普通字典那样会报错,这里返回1, 因为程序里有__getitem__ 打印i['name']时候,会先执行__getitem__方法,找item,因为name被删除了,所以就找不到返回'1'
del i.name #object 原生支持 __delattr__ print(i.name) #这种删除会报错
#也可以查看一下对象中的内容,看看有没有被删除 print(i.__dict__) # {'age': 38}
进阶

import json from collections import namedtuple Card = namedtuple('Card',['rank','suit']) # rank 牌面的大小 suit牌面的花色 class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') # 2-A suits = ['红心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] def __setitem__(self, key, value): self._cards[key] = value def __str__(self): return json.dumps(self._cards,ensure_ascii=False) deck = FranchDeck() print(deck[10]) from random import choice print(choice(deck)) # print(choice(deck)) from random import shuffle shuffle(deck) print(deck[10]) print(deck) print(deck[:5])