自定制格式化字符串__format__
__str__ , __repr__(优先使用,覆盖面广)
改变对象的字符串显示__str__,__repr__
class A:pass a = A() print(a) # <__main__.A object at 0x0000000001DD1D68>内存地址 自己找不到到父类找
l = list()
print(l) # [] 为什么打出来长上面的不一样,因为list里面有内置方法
print(a.__str__()) # <__main__.A object at 0x00000000021C7A20> # 打印一个对象的时候,实际上市调用了这个对象所在类的__str__方法,打印的是这个方法的返回值 print('%s'%a) # <__main__.A object at 0x0000000002197A58> # %s 就是__str__方法的返回值 # 类的双下划线方法 # __str__ 和 __repr__
自己定制str方法 class A: def __str__(self): return 'a的对象' # str必须return一个字符串 def __repr__(self): return 'repr:A的对象' a = A() print(a.__str__()) # a的对象 print(a.__repr__()) # repr:A的对象 repr是str的备胎,没有str就用repr # repr是str的备胎,没有str就用repr (repr比较随和) # str 却不能给repr做备胎 (str高冷 ) class A: # def __str__(self): # return 'a的对象' # str必须return一个字符串 def __repr__(self): return 'repr:A的对象' a = A() print(a) # repr:A的对象 # 本质调用 __str__, 如果没有实现,就调用__repr__,再找不到,用object父类的 print(a.__str__()) # repr:A的对象 print(a.__repr__()) # repr:A的对象 print('%s'%a) # repr:A的对象 # 打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值
%s %r
class A: def __str__(self): return 'a的对象' # str必须return一个字符串 def __repr__(self): return 'repr:A的对象' a = A() print(a.__str__()) # a的对象 print(a.__repr__()) # repr:A的对象 repr是str的备胎,没有str就用repr print('%s'%a) # s -- 》 str a的对象(自己有用自己) print('%r'%a) # r --》 repr repr:A的对象
自定制格式化字符串__format__
格式
# format_dict={ # 'nat':'{o.name}-{o.addr}-{o.type}',#学校名-学校地址-学校类型 # 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 # 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 # }
class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __format__(self, format_spec): #format_spec = 'nat' 相当与上面 fmt='{obj.type}:{obj.name}:{obj.addr}' # 做格式化输出 return fmt.format(obj=self) # 这里obj=self为固定写法 s1=School('oldboy1','北京','私立') print(format(s1,'nat')) print(format(s1,'tna')) print(format(s1,'tan')) print(format(s1,'asfdasdffd'))
例子
class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __format__(self, format_spec): #format_spec = 'nat' fmt='''===================== 姓名 : {obj.name} 班级 : {obj.addr} =====================''' return fmt.format(obj=self) s1=School('oldboy1','北京','私立') print(format(s1,'nat')) print(format(s1,'tna')) print(format(s1,'tan')) print(format(s1,'asfdasdffd')) # 输出的格式 # ===================== # 姓名 : oldboy1 # 班级 : 北京 # ===================== # ===================== # 姓名 : oldboy1 # 班级 : 北京 # ===================== # ===================== # 姓名 : oldboy1 # 班级 : 北京 # ===================== # ===================== # 姓名 : oldboy1 # 班级 : 北京 # =====================
__del__
析构方法
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
析构方法(是执行删除对象的时候才执行)700百才启动
具有周期: 当没引用
须知道: 当你删除一个对象的时候,这个对象的相关内容,需做一些处理,就使用析构方法
# 用于高并发问题 class A: def __del__(self): ''' 析构方法 这个方法只有在执行del A类的对象的时候才被触发 且先执行代码中的内容,再删除对象 如果我删除了这个对象,它跟着还有一些其他的附属的内容也没有用了 我们就可以在这个方法中回收掉 ''' print('执行我啦!') self.b.close() f = open('file','w') a = A() # 对象 a.b = f # 给a的对象赋一个文件句柄 del a # 即文件不需要了
item系列方法
__getitem__\__setitem__\__delitem__
需求:
使用[] 去获取对象里面内容的方法,实现,调用就使用item系列方法
#关于item : 对象访问 如果是 对象名[],是因为内部实现了item系列的方法
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]时,我执行') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key时,我执行') self.__dict__.pop(item) f1 = Foo('sb') # 访问属性的方式变了 # 对象名.属性 f1=Foo('sb') f1['age']=18 #给f1添加一个属性 # 触发 __setitem__(self, key, value) ---》 key = age ,value = 18 del f1['age'] #删除属性 __delitem__(self, key) print(f1['name']) # f1.name 正常以前访问 # 触发了__getitem__(self, item) --> item = name f1.__dict__['age'] = 18 f1['age1']=19 del f1.age1 #删除属性 f1['name']='alex' print(f1.__dict__)
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): if item == 1: print('hahaha') def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]时,我执行') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key时,我执行') self.__dict__.pop(item) f1 = Foo('sb') f1[1] # 输出 hahha
__new__(面试)
是object替你执行new方法
对象的实例化
创造一个裸地对象 —— __new__ ****
初始化
单例模式 —— 设计模式(面试)
一个类 从头到尾 只创建 一个对象
class Singleton: def __new__(cls, *args): if not hasattr(cls, '_instance'): cls._instance = object.__new__(cls) # 创造一个新对象 return cls._instance def __init__(self,name): self.name = name one = Singleton('alex') # object.__new__(elax) print(one.name) # alex two = one two.name = 'egon' two = Singleton('egon') print(two.name) # egon print(one.name) # egon print(id(one),id(two)) # 38785880 38785880
__call__
()跟call是约定的
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') Foo()() #对象名() ---> 调用call
__len__
class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a))
__hash__
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(hash(a))
__eq__
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return True a = A() b = A() print(a == b)
例子
class A: def __eq__(self,obj): #equal : 相等 # if self.a == obj.a and self.b == obj.b: return True a = A() b = A() a.name = 'alex' b.name = 'egon' print(a == b) # True
面试题
一个类 有 100个 对象,每一个对象都拥有三个属性:name,sex,age 如果两个对象的name和sex属性完全一致 我就认为这是一个对象 请对这100个对象进行去重 class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash(self.name+self.sex) def __eq__(self, other): if self.name == other.name and self.sex == other.sex:return True p_lst = [] for i in range(84): p_lst.append(Person('egon',i,'male')) print(set(p_lst))