类的继承
类继承有三种调用方式,其实是 有区别 的,听我慢慢道来class A: def say(self, name): print(f'Im {name}')class B(A): def say(self, name): # 第一种:父类.方法(self, 参数) 直接调用 A.say(self, name) def say(self, name): # 第二种:super().方法(参数) 直接调用 # 在谁的类下调用super,就找此类对应 mro()的下一个,就是要继承的 super().say(name) def say(self, name): # 第三种:super(B, self).方法(参数) # 找类名 对应的 mro()的下一个,就是 继承的,一般写本身的类名 super(B, self).say(name)B().say('Tom')
上下文管理器
""" 上下文管理器可以用两种方式实现:""" 方式1:通过类来实现 主要实现两种协议 1. __enter__(self) 2. __exit__(self, *args, **kwargs) class A(): def __init__(self, name): self.name = name def __enter__(self): print('进入') return self def __exit__(self, *args, **kwargs): print('退出') return True with A('Tom') as a: print(a.name) 方式2:通过函数来实现 from contextlib import contextmanager @contextmanager def f(): print('开始') # yield 之前 对应 with f() yield '中间' # yield 的值 就是 as 之后的值 print('结束') # yield 之后 对应 print(str1) 这个语句体 with f() as str1: print(str1) ------------------Output---------------------- 开始 中间 结束
属性描述符-property-setter
class A:@propertydef name(self): return '123'@name.setterdef name(self, value): self.age=valuea = A()print(a.name)a.name = '456'print(a.age)
__init__()
实例化对象时自动调用,这里先卖个关子,见下面 __new__()
__call__()
""" 对象当做函数执行的时候会自动调用 __call__()"""class A(): passa = A() # 此处自动调用了 __init__()a() # 此处自动调用了 __call__()
__str__()
""" 对对象进行print操作的时候 会自动调用 __str__()"""class A: def __str__(self): return '5'a = A()print(a) # 此处自动调用了 __str__()
__new__()
""" 上面说过 __init__()是实例化对象的时候自动调用,在它之前还隐式调用了 __new__() __new__返回的是什么,对象就是什么"""In [2]: class A: ...: def __new__(self): ...: print('__new__') # 初始化对象只调用 __new__ 而不调用 __init__ ...: return 1 ...: def __init__(self): ...: print(2) ...: print(A()) __new__ 1
__setattr__() 和 __getattr__() 和 __delattr__()
""" __setattr__():=号 属性赋值 会自动调用此方法 __getattr__():.号 属性取值 会自动调用此方法 # 注:找不到属性才会调用此方法 __delattr__():del 属性删除 会自动调用此方法"""class A: def __init__(self, name): self.name = name # 赋值操作就会调用 __setattr__() def __setattr__(self, name, value): print(f'{name}:{value}') def __getattr__(self, name): print(name) def __delattr__(self,name): print('del了') a = A('Jack') # 调用了 __init__a.name = 'Tom' # 赋值操作再次调用 __setattr__()a.name # 取值操作调用 __getattr__()---------------------output---------------------name:Jackname:Tomnamedel了
__getattribute__()
""" 和 __getattr__() 一样,只不过 __getattribute__最先调用,并拦截了 __getattr__()"""class A: def __init__(self): self.name = 1 def __getattr__(self,x,*args, **kwargs): print(456) def __getattribute__(self, x): print(123)a = A()a.aaaaaa-----------output---------------123
__getitem__()
""" 对对象进行 切片、索引、遍历 等 会自动调用此方法"""class A:def __getitem__(self,x,*args, **kwargs): return xa = A()触发方式1: 如果直接索引此对象,那么索引值就会传递到上面 x 当作参数 print(a[5]) >> 5触发方式2: 如果直接切片此对象,那么slice对象 就会传递到上面 x 当作参数 print(a[1:5]) >> slice(1, 5, None)触发方式3: 如果for循环迭代此对象,那么 上面的 x 每次将会被赋予从零开始 自增1的自然整数 for x in a: print(x) >> 0,1,2,3,4....................
__init_subclass__()
""" 被继承的类 会自动调用__init_subclass__ """class A: def __init_subclass__(self): print('我被继承了')class B(A): pass
__base__()
""" 查看基类"""class A: passclass B(A): passprint(B.__base__)-----------output---------------<class '__main__.A'>
__contains__()
""" xx in xx 就会自动调用 __contains__()"""