4-19 面向对象 的内置方法
1,__str__ 和 __repr__
__str__就是改变对象的字符串显示。
Python有一个内置的函数叫repr,它能把一个对象用字符串的形式表达出来以便辨认,这就是“字符串表示形式”。repr就是通过__repr__这个特殊方法来得到一个对象的字符串表示形式。如果没有实现__repr__,当我们再控制台里打印一个变量的实例时,得到的字符串可能会是<__main__.Object at 0x14af07dbe80>,这个表示的是打印的对象,以及对象的内存地址。
str()的结果是依赖obj.__str__()
print(obj)的结果是依赖obj.__str__()
%s的结果是依赖obj.__str__()
repr的结果是依赖obj.__repr__()
%r的结果是依赖obj.__repr__()
所以说repr是str得到备胎。
在类中,当把对象作为参数传入print()时,会自动调用对象的__str__方法,但是当__str__方法不存在时,则会调用__repr__方法。
所以,如果你只想实现这两个特殊方法中的一个,建议还是选择__repr__方法。
class List: def __init__(self,*args): self.l = list(args) def __str__(self): return '[%s]'%(','.join([str(i) for i in self.l])) l = List(1,2,3,4,5) print(l) #--> l.__str__() # object类中的__str__就是返回一个数据的内存地址 print(l) print(str(l)) print('%s'%l) print(obj) 的结果 是 obj.__str__()的结果 str(obj)
因为class int 和class str 的__repr__的方法不同。
class int: def __repr__(self): return str(1) class str2: def __repr__(self): return "%s"%str(1) a = int() b = str2() print(repr(a)) print(repr(b))
2,__format__
在类中自定义字符串的格式化输出。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
format_dict={ 'nat':'{obj.name}-{obj.addr}-{obj.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): if not format_spec or format_spec not in format_dict: format_spec = 'nat' fmt = format_dict[format_spec] return fmt.format(obj=self) s1 = School('oldboy1','北京','私立') print(format(s1,'nat')) print(format(s1,'tna')) print(format(s1,'tan')) print(format(s1,'asadafsfsf'))
3,__del__
析构方法,在删除一个对象的时候,做了一些收尾工作。
class A:
def __init__(self):
self.f = open('文件','w')
def __del__(self):
self.f.close()
print('执行我啦')
a = A()
del a
print(a)
print('aaa')
4,__new__构造方法
创建对象的过程就是__new__: 对象的创建,是一个静态方法,第一个参数是cls。(想想也是,不可能是self,对象还没创建,哪来的self)
利用这个方法和类属性的特性可以实现设计模式中的单例模式.单例模式是指创建唯一对象吗,单例模式设计的类只能实例化一个对象。
class B: __instance = None def __new__(cls, *args, **kwargs): if cls.__instance is None: obj = object.__new__(cls) cls.__instance = obj return cls.__instance def __init__(self,name,age): self.name = name self.age = age def func(self): print(self.name) a = B('alex',80) b = B('egon',20) print(a) print(b) print(a.name) print(b.name)
5,__call__ (callable就是判断一个对象可否被调用)
在类内一个对象是否可调用 完全取决于这个对象对应的类是否实现了__call__内置方法。
class Teacher: def __call__(self): print(123) def call(self):print(123) t = Teacher() #t.call() t() print(callable(Teacher)) print(callable(t))
6,__eq__ == 判断self对象是否等于other对象
class A: def __eq__(self, other): # if self.__dict__ == other.__dict__: return True # __eq__() a = A() a.name = 'alex' b = A() b.name = 'egon' print(a) print(b) print(a == b)
7,__items__系列
__getitem__(self,key):返回键对应的值。
__setitem__(self,key,value):设置给定键的值。
__delitem__(self,key):删除给定键对应的元素。
当我们对类的属性item进行下标的操作时,首先会被__getitem__()、__setitem__()、__delitem__()拦截,从而进行我们在方法中设定的操作,如赋值,修改内容,删除内容等等。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo: def __init__(self,name): self.name=name def __getitem__(self,item): return self.__dict__[item] def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]时,我执行') self.__dict__.pop(key) f = Foo('alex') # f.name = ... print(f['name']) # f.__getitem__('name') f['age'] = 18 # 赋值 print(f.age) # 自带的语法 print(f['age']) # 修改 f['age'] = 80 print(f['age']) print(f.__dict__)# 通过实现__getitem__得到的 del f['age'] print(f.age) # 删除