类的继承

类继承有三种调用方式,其实是 有区别 的,听我慢慢道来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__()"""