一. 内置方法,进阶
双下方法:
内置函数/特殊语法/语法糖/内置的模块
1. __call__ 相当于 对象()调用__call__方法 [flask (django)]
A()() # 类名()(), 调用__call__方法
相当于先实例化得到一个对象,在对对象(),==>和上面的结果一样, 相当于调用__call__方法
2. __new__ 特别重要 开辟内存空间的 类的构造方法 有return
1. 开辟一个空间,属于对象的 obj = object.__new__(cls) # 创建一个空间(内存地址)
2. 把对象的空间传给self,执行init
3. 将这个对象的空间返回给调用者
3. __len__ len(obj) 调用了 __len__这个方法 有return
内置函数和类的内置方法是有联系的
len(obj)相当于调用了这个obj的__len__方法
__len__方法return的值就是len函数的返回值
如果一个obj对象没有__len__方法,那么len函数会报错
4. __str__ str(obj), '%s' % obj, print(obj) 有return
print一个对象相当于调用一个对象的__str__方法
内置的数据类型,内置的类,相当于执行__str__ print(str(对象))
__str__: str(obj), 要求obj必须实现了__str__, 要求这个方法的返回值必须是字符串str类型
print % s
5. __init__ 特殊语法 初始化方法,在实例化的时候__new__之后调用
6. __repr__ : 是 __str__的备胎,如果有__str__方法,那么 print %s str
都先执行__str__方法,并且使用__str__返回值
如果没有__str__,那么 print %s str都会执行repr
repr(obj),%r
在子类中使用__str__,先找子类的__str__,没有的话要向上找,只要父类不是object,就执行父类的__str__
但是如果除了object之外的父类都没有__str__,就执行子类的__repr__,如果子类也没有,还要
向上继续找父类的__repr__方法.
一直找不到,就打印某某对象的内存地址
__repr__,__str__
__repr__ repr %r
__str__ print %s str
如果没有str,所有原本要调用__str__方法的语法,都会调用__repr__
反过来如果没有repr,会使用父类的repr,str不能替代
在继承中: 如果子类没有str,会先到父类找str,再找子类的repr - 扩展
所有的双下方法, 没有 需要你在外部直接调用的
而是总有一些其他的 内置函数 特殊的语法 来自动触发这些 双下方法
1. __call__ 方法
class Apple(): def __call__(self, *args, **kwargs): print('__call__方法 ...') class Banana(Apple): def __init__(self,call): self.call = call() # 这里相当于一个类的实例化对象 self.call() # 通过self.call(是一个对象)是拿到一个类的实例化 再加(),就是执行__call__方法 A = Apple() A() # 对象A加 () 执行__call__方法,或者类名Apple加()()也是执行__call__方法 B = Banana(Apple) # 传一个类名
2. __new__和__init__方法
class Apple: def __new__(cls, *args, **kwargs): # 在执行new根本没有创建空间,只能转类的空间 obj = object.__new__(cls) # 对象的地址 self,obj print("在new方法里",obj) return obj def __init__(self): print("在init方法里",self) obj = Apple() print(obj) # 单例类(比较重要) # 如果这个类,从头到尾只能有一个实例,那么这个类就是一个单例类 class Apple: __apple = None def __new__(cls, *args, **kwargs): if not cls.__apple: # 判断是否存在 cls.__apple = object.__new__(cls) # 对象地址 return cls.__apple def __init__(self): pass a1 = Apple() a2 = Apple() print(a1) print(a2) # 解释: 通过一次Apple()的实例化对象a1, 执行 __new__方法, # 判断cls.__apple == None:, 所以就是不存在,就执行下面的 # 代码,把a1的对象地址,通过__new__方法传给cls.__apple, # 所以cls.__apple,就拿到了a1的对象地址,cls.__apple == a1 # 第二次实例化对象a2, 执行__new__方法,判断存在cls.__apple它, # 是一个a1的对象地址,所以就不执行if里面的内容,直接把a1的对象 # 地址返回给了a2,所以 a2 = a1 ,的内存地址,就是一个单例类. # 总的来说就是开头设置一个不存的属性,把第一次的对象地址通过判断 # 传给它,在把对象地址返回给原来的对象,实例化第二次的时候,发现 # 通过判断哪个属性存在值了,就不去执行了,返回哪个存在的值(就是 # 第一次实例化对象的地址)给第二次的对象,
3. __len__和__iter__方法
class Len: def __init__(self): pass def __len__(self): print("执行__len__了") return len(self.__dict__) # 返回的是对象属性的多少 len意思是长度 def __iter__(self): print('执行__iter__方法...') return len(self.__dict__) a = Len() len(a) # len(对象) 执行len这个方法 print(len(a)) # 调用了__len__方法,和接收返回值 # len(obj)相当于调用了这个obj的__len__方法 # __len__方法return的值就是len函数的返回值 # 如果一个obj对象没有__len__方法,那么len函数会报错 a.__iter__() # 相当于调用了__iter__方法 print(a.__iter__()) # 调用了__iter__方法,和接收返回值
4. __str__和__repr__方法
class Apple: def __str__(self): return "%s %s %s" % (self.school,self.classmate,self.name) def __init__(self,school,classmate,name): self.school = school self.classmate = classmate self.name = name a = Apple("XXXX","X",18) print(a) # 相当于执行了__str__方法 print(str(a)) # 内置的数据类型,内置的类,相当于执行__str__ class Apple: def __init__(self,school): self.school = school def __str__(self): # 先找__str__方法打印,然后再找__repr__方法 return "Apple %s __str__..." % self.school def __repr__(self): return 'Apple __repr__...' class Banana(Apple): def __str__(self): # 先找本类的__str__方法打印,然后再到父类找__str__方法,没有的话,找__repr__方法替代 return "Banana %s __str__..." % self.school def __repr__(self): return "Banana __repr__..." a = Banana("苹果") print(a) # 执行 __str__方法,如果没有__str__方法会找__repr__方法去执行 print(str(a),repr(a)) # 如果没有__repr__方法,会打印出对象的地址 print("%s | %r" % (a,a))