python中的抽象类、接口类、元类、动态类、新式类、旧式类

元类有什么用

元类可以动态地创建类,它是制造类的工厂

类(class)实例化 一个 instance对象

type 的实例化就是 类class对象

type 是 Python 自建的元类

type () 函数能返回一个对象的类型 (类型本身也是对象),也就是返回对象的__class__属性值。

如何创建 class 对象呢?

最简单的办法

ini 复制代码
class MyClass: #python3默认是创建新式类,隐式继承了object
    a = 1

type函数

go 复制代码
type(name, bases, namespace)

MyClass = type('MyClass', (object,), dict(a=1))

-   name 对应于类的`__name__`属性
-   bases 对应于类的`__bases__`属性
-   namespace 对应于类的`__dict__`属性

动态类

type() 函数可以动态创建类,即在运行期动态创建类

如何控制类的创建行为?

使用 metaclass

比如我们想让自定义的类所创建的的对象自动包含 add 方法,即使类本身没有定义这个方法

python 复制代码
# metaclass是类的模板,所以必须从`type`类型派生:
class ListMetaclass(type):
    # __new__ 是在__init__之前被调用的特殊方法
    # __new__是用来创建对象并返回这个对象
    # 而__init__只是将传入的参数初始化给对象
    # 实际中,你很少会用到__new__,除非你希望能够控制对象的创建
    # 在这里,类是我们要创建的对象,我们希望能够自定义它,所以我们改写了__new__
    # 如果你希望的话,你也可以在__init__中做些事情
    # 还有一些高级的用法会涉及到改写__call__,但这里我们就先不这样.
    def __new__(cls, name, bases, attrs):
        # cls:当前创建的类对象
        # name:类的名字
        # bases:类继承的父类集合
        # attrs:类的方法集合。
        print('name: ', name) # 这些打印会在创建MyList类对象的时候打印,而非在创建MyList实例对象的时候
        print('bases: ',bases)
        print('attrs: ', attrs)
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

class MyList(list, metaclass=ListMetaclass):
    pass

输出

python 复制代码
name:  MyList
bases:  (<class 'list'>,)
attrs:  {'__module__': '__main__', '__qualname__': 'MyList'}
>>> l=MyList() # 在创建MyList类的时候自动获得了add属性,即一个函数对象
>>> l.add('test1')
>>> l.add('test2')
>>> l
['test1', 'test2']

接口类

一种规范 规定子类应该具备的功能

定义了一些接口(就是函数,但这些函数都没有具体的实现),必须由引用类继承接口类

  • 接口的设计目的是 "协作" 与 "解耦合"
  • 接口类中没有实现所有的方法
  • 鸭子类型算是一种接口类的实现风格
ruby 复制代码
class Payment: # 接口类
    def pay(self, money):
        raise NotImplementedError

class AliPay(Payment): # 引用类具体实现
    def pay(self, money):
        print('AliPay')

class AppPay(Payment):
    def pay(self, money):
        print('AppPay')

class WeichatPay(Payment):
    def zhifu(self, money):
        print('WeichatPay')

def pay(payment, money):
    # 如果实现类没有提供pay方法,在运行的过程就会报异常,
    # 这也是我们接下来要介绍的抽象类存在的目的
    payment.pay(money)
    
>>> p = WeichatPay()
>>> pay(p, 40) # 抛出NotImplementedError

抽象类

一种规范 规定子类应该具备的功能

该类不能被实例化,只能被继承,且子类必须实现抽象方法

  • 抽象类的设计目的更多的是 "复用"
  • 抽象类实现部分方法
  • abc 模块就是用来实现抽象类的
  • 抽象基类的目的就是让别的类继承它以及实现特定的抽象方法
  • 可以去使用抽象基类做类型检查,这样就确保了子类实现了某些特定的方法

实现抽象基类的方法就是通过使用 abc 这个内建模块

python 复制代码
import abc

class Payment(abc.ABC):    # 使用抽象基类实现接口类
    # Payment是一个抽象基类,因为它继承了abc.ABC。
    # 另外,你也可以让它从元类ABCMeta直接创建

    # abc.abstractmethod这个装饰器去标记抽象方法
    # 实现细节由子类去完成
    @abc.abstractmethod
    def pay(self):
        pass

class AliPay(Payment): # 引用类具体实现
    def pay(self, money):
        print('AliPay')

class AppPay(Payment):
    def pay(self, money):
        print('AppPay')

class WeichatPay(Payment):
    def zhifu(self, money):
        print('WeichatPay')
        
>>> p = AliPay()
>>> isinstance(p, Payment)
True
>>> wp = WeichatPay() # 这里就直接报错了
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Cant instantiate abstract class WeichatPay with abstract methods

新式类和旧式类

Python 2.x 中默认都是经典类,只有显式继承了 object 才是新式类。

Python 3.x 中默认都是新式类,不必显式的继承 object

新式类对象可以直接通过__class__属性获取自身类型

新式类增加了__slots__内置属性,可以把实例属性的种类锁定到__slots__规定的范围之中

新式类采用广度优先搜索(bfs),而旧式类是采用深度优先搜索(dfs)

新式类增加了__getattribute__方法

继承搜索的顺序发生了改变

经典类多继承属性搜索顺序:

先深入继承树左侧,再返回,开始找右侧; 深度优先搜索(dfs)

新式类多继承属性搜索顺序

先水平搜索,然后再向上移动 广度优先搜索(bfs)

相关推荐
颜淡慕潇24 分钟前
【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
后端·云原生·容器·kubernetes·问题解决
尘浮生1 小时前
Java项目实战II基于Spring Boot的光影视频平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
尚学教辅学习资料1 小时前
基于SpringBoot的医药管理系统+LW示例参考
java·spring boot·后端·java毕业设计·医药管理
monkey_meng3 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马3 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng3 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
paopaokaka_luck7 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
码农小旋风9 小时前
详解K8S--声明式API
后端
Peter_chq9 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml49 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍