理解python元类

一、元类是什么?

在python中,一切皆对象,无论是列表、元组,还是函数、类,它们都是对象。
把一个类看作对象,即类对象,一个类对象的类就是元类。
通俗来说就是,元类是类的祖宗
可能这里描述的还是不清楚,下面举例解释:
首先我们用class 来检索一个对象对应的类

class main():
    pass
print(main.__class__)
print(str.__class__)
>>>
<class 'type'>
<class 'type'>

上述代码中,无论我们自己创建的类main,还是‘str’,它们对应的类都是‘type’。
那‘type’本身对应的类是什么呢?

print(type.__class__)
>>>
<class 'type'>

结果‘type’对应的类还是‘type’。
这里,‘type’就是元类(类的祖宗,hah),创建其他类的类。

二、类type

那‘type’类到底有什么用呢?
可以查看下源码:

class type(object):
    """
    type(object_or_name, bases, dict)
    type(object) -> the object's type
    type(name, bases, dict) -> a new type
    """
  • 获取一个对象的类型,这个很常用。
print(type('1234'))
print(type(1234))
>>>
<class 'str'>
<class 'int'>
  • 定义一个新类型。
    用法:
type(类名, 父类(可以为空),属性的字典(名称和值))

一个类必然包含以下三个部分:

  • 类名
  • 类的继承关系
  • 类的属性
    常规定义类的方法如下
class main():
    first = True

使用type定义类:

main = type('main', (), {first:True})

使用type类可以创建其他的类,type类就是一个元类。
type不仅是其他类的元类,也是自己类的元类。

三、元类的作用

以上说明了元类是什么和type元类,那元类到底能干嘛?

(一)元类的作用区间

先说下创建类的过程,来说明元类在哪里起作用的。
一般定义类的时候,top函数是__init__,也就是初始化函数,但是实际上python中,实例化一个对象的过程,首先调用的是__new__函数,其次才是__init__函数。
__new__函数创建类的实例,并返回该实例,再调用__init__函数初始化实例,这样一个完整的实例就生成了。

class People(object):

    def __init__(self, name, gender):
        # 初始化实例
        print(self)
        print('init函数')
        self.name = name
        self.age = gender

    def __new__(cls, *args, **kwargs):
        # 创建实例,并返回实例
        print(cls)
        print(cls.__class__)
        print('new函数')
        obj = super().__new__(cls)
        return obj
student = People('WWW', M)
>>>
<class '__main__.People'>
<class 'type'>
new函数
<__main__.People object at 0x000001E05919EEF0>
init函数

由返回结果可以看出在类创建时,先调用__new__函数创建了实例。·而元类type在__new__函数作用区间生成了类。
所以元类会控制类生成的过程,并在其中产生了影响。
下面就可以说它的作用了。

(二)元类的作用

1、手动创建类

如上面使用type元类手动创建一个新类。

main = type('main', (), {first:True})
2、自定义元类

定义一个新的元类,继承type,重新定义此类。

class MetaClass(type):
    def __new__(cls, name, bases, attrs):
        print(cls)
        A = super(MetaClass, cls).__new__(cls, name, bases, attrs)
        print(A)
        return A

    def __init__(self, *args, **kwargs):
        super(MetaClass, self).__init__(*args, **kwargs)
        print(self)


class P(object, metaclass=MetaClass):
    pass
 >>>
<class '__main__.MetaClass'>
<class '__main__.P'>
<class '__main__.P'>

增加__call__函数,可以控制实例对象的结果。

class MetaClass(type):
    def __new__(cls, name, bases, attrs):
        print(cls)
        A = super(MetaClass, cls).__new__(cls, name, bases, attrs)
        print(A)
        return A

    def __init__(self, *args, **kwargs):
        super(MetaClass, self).__init__(*args, **kwargs)
        print(self)

    def __call__(self, *args, **kwargs):
        B = super(MetaClass, self).__call__(*args, **kwargs)
        print(B)
        return B


class P(object, metaclass=MetaClass):
    pass


if __name__ == '__main__':
    a = P()
 >>>
<class '__main__.MetaClass'>
<class '__main__.P'>
<class '__main__.P'>
<__main__.P object at 0x000002167148E668>
3、元类写单例模式
class MetaClass(type):
    instance = None
    
     def __call__(self, *args, **kwargs):
        if self.instance is None:
            self.instance = super(MetaClass, self).__call__(*args, **kwargs)
        return self.instance


class P(object, metaclass=MetaClass):
    pass


if __name__ == '__main__':
    a = P()
    b = P()
    print(id(a), id(b))
    if id(a) == id(b):
        print('True')
 >>>
1733009417272 1733009417272
True
4、使用元类动态编写类
class MetaClass(type):
    def __new__(cls, name, bases, attrs):
        if name == 'A':
            attrs['add'] = lambda self, value: self.append(value)
        else:
            pass
        return super(MetaClass, cls).__new__(cls, name, bases, attrs)


class A(list, metaclass=MetaClass):
    pass

class B(list, metaclass=MetaClass):
    pass

if __name__ == "__main__":
    a = A()
    a.add("123")
    b = B()
    print(a, b)
>>>
['123'] []
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值