5.深入类和对象

5.1鸭子类型和多态

鸭子类型:

不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。

5.2抽象基类(abc模块)

做接口的强制规定。

所有的抽象基类里的metaclass都是ABCMeta

不能实例化

import abc

class CacheBase(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def get(self, key):
        pass

    @abc.abstractmethod
    def set(self, key, val):
        pass

class RedisCache(CacheBase):
    pass

redis_cache = RedisCache()

5.3isinstance与type区别

class A():
    pass

class B(A):
    pass

b = B()
print(isinstance(b,B)) #True
print(isinstance(b,A)) #True
print(type(b)) #<class '__main__.B'>
print(type(b) is A) #False

5.4对象(实例)变量和类变量

class A:
    # 类变量
    aa = 1
    # self是类的实例
    def __init__(self, x, y):
        self.x = x
        self.y = y

a = A(2,3)
# a.aa:a是实例,没有aa变量,就会向上查找类A的aa变量
print(a.x,a.y,a.aa) # 2 3 1
print(A.aa) # 1
print(A.x) #AttributeError: type object 'A' has no attribute 'x'
class A:
    # 类变量
    aa = 1
    # self是类的实例
    def __init__(self, x, y):
        self.x = x
        self.y = y

a = A(2,3)
A.aa = 11 #修改 类中aa的值
a.aa = 100 #在实例对象中新增aa变量
# a.aa:a是实例,查找由下往上,实例对象有aa变量 故aa=100
print(a.x,a.y,a.aa) # 2 3 100
print(A.aa) # 11
print(A.x) #AttributeError: type object 'A' has no attribute 'x'

5.5类属性和实例属性以及查找顺序

c3算法

#c3算法
class D:
    pass

class B(D):
    pass

class E:
    pass

class C(E):
    pass

class A(B,C):
    pass
    
print(A.__mro__)    
#(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)    

#c3算法
class D:
    pass

class B(D):
    pass


class C(D):
    pass

class A(B,C):
    pass

print(A.__mro__)
#(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)

5.6静态方法、类方法以及对象方法以及参数

class Date:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

    # 实例方法
    def tomorrow(self):
        self.day+=1

    # 静态方法  调用:必须Date.调用  硬编码 类名有变动时,需修改代码
    @staticmethod
    def parse_from_string(data_str):
        year,month,day = tuple(data_str.split("-"))
        return Date(int(year),int(month),int(day))

    #类方法  类名有变动时,无需修改代码
    @classmethod
    def from_str(cls,data_str):
        year, month, day = tuple(data_str.split("-"))
        return cls(int(year), int(month), int(day))

    def __str__(self):
        return "{year}/{month}/{day}".format(year=self.year,month=self.month,day=self.day)


if __name__ == "__main__":
    new_ = Date.from_str("2018-5-2")
    print(new_)

5.7数据封装和私有属性

class User:
    def __init__(self,birthday):
        # 私有实例变量  实例对象无法获取、子类无法获取 ; 实际变形后的名称为:_User__birthday
        self.__birthday = birthday
    def get_age(self):
        return 2019 - int(self.__birthday)

if __name__ == "__main__":
    user = User("1992")
    print(user.get_age())
    print(user._User__birthday)
    # print(user.__birthday)

5.8python的自省机制

通过一定的机制(如__dict__/dir())查询到对象的内部结构

class User:
    def __init__(self,birthday):
        # 私有实例变量  实例对象无法获取、子类无法获取 ; 实际变形后的名称为:_User__birthday
        self.__birthday = birthday
    def get_age(self):
        return 2019 - int(self.__birthday)

if __name__ == "__main__":
    user = User("1992")
    print(user.get_age())
    print(user._User__birthday)
    # print(user.__birthday)

5.9super函数

from threading import Thread
class MyThread(Thread):
    def __init__(self,name,user):
        self.user = user
        # 复用父类代码
        super().__init__(name=name)
class A:
    def __init__(self):
        print("A")

class B(A):
    def __init__(self):
        print("B")
        # 是调用mro顺序中下一个的类的构造函数
        super().__init__()

class C(A):
    def __init__(self):
        print("C")
        super().__init__()

class D(B,C):
    def __init__(self):
        print("D")
        super(D,self).__init__()

if __name__ =="__main__":
    print(D.__mro__)
    d=D()
    
#(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
D
B
C
A

5.10 django rest framework 中对多继承使用的经验

特点:

Mixin类功能单一

不和基类关联,可以和任意基类组合,基类可以不和Mixin关联就能初始化成功

在Minxi中不要使用super这种用户

5.11python中with语句

import contextlib

@contextlib.contextmanager
def func1():
    print("enter...")
    yield {}
    print("exit...")

with func1() as func2:
    print("tt...")
# enter...
# tt...
# exit...
class A():
    def __enter__(self):
        print("enter...")
        return self
    def f(self):
        print('f')
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit...')

with A() as a:
    a.f()
# enter...
# f
# exit...


猜你喜欢

转载自blog.csdn.net/weixin_40744265/article/details/89027871