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

元类有什么用

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

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

type 的实例化就是 类class对象

type 是 Python 自建的元类

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

如何创建 class 对象呢?

最简单的办法

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

type函数

type(name, bases, namespace)

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

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

动态类

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

如何控制类的创建行为?

使用 metaclass

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

# 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

输出

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

接口类

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

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

  • 接口的设计目的是 “协作” 与 “解耦合”
  • 接口类中没有实现所有的方法
  • 鸭子类型算是一种接口类的实现风格
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 这个内建模块

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)

---------------------------END---------------------------

题外话

感谢你能看到最后,给大家准备了一些福利!

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。


👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img

二、Python兼职渠道推荐*

学的同时助你创收,每天花1-2小时兼职,轻松稿定生活费.
在这里插入图片描述

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

👉 CSDN大礼包:gift::[全网最全《Python学习资料》免费赠送:free:!](https://blog.csdn.net/weixin_68789096/article/details/132275547?spm=1001.2014.3001.5502) (安全链接,放心点击)

若有侵权,请联系删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值