类的继承
类继承有三种调用方式,实际上是 有区别 的,听我慢慢道来
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:
@property
def name(self):
return '123'
@name.setter
def name(self, value):
self.age=value
a = A()
print(a.name)
a.name = '456'
print(a.age)
__init__()
实例化对象时自动调用,这里先卖个关子,见下面 __new__()
__call__()
"""
对象当作函数执行的时候会自动调用 __call__()
"""
class A():
pass
a = 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:Jack
name:Tom
name
del了
__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 x
a = 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:
pass
class B(A):
pass
print(B.__base__)
-----------output---------------
<class '__main__.A'>
__contains__()
"""
xx in xx 就会自动调用 __contains__()
"""