[知识总结]python中元类的理解--类的创建流程(Python)

本文深入探讨了Python中元类的概念及应用,详细介绍了类对象的创建流程,并通过代码实验展示了对象实例化的具体过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.对python中对象的理解:

要想理解类的创建流程,首先需要理解python中对象的概念。

在python中,一切皆对象,这句话的含义可以具体化为:

1.都可以被引用

2.都可以当做函数的参数传入

3.都可以当做函数的返回值

4.都可以作为容器类的元素

2.元类的含义:

在python中创建一个类我想大家都不陌生,用class关键字就可以了:

class People:
    pass     # 仅做演示

类创建完毕后,我们就可以用这个类来实例化对象了:

p1 = People()

看见没,用类实例化对象其实就是在类名后面加上小括号调用类,这和函数的调用很像。

下面,我们的问题来了:既然在python中一切皆对象,那么作为类的People是不是也是一个对象呢?

答案是:是的!类People也是一个对象。

问题又来了,既然是对象,那么People也一定也需要一个类来实例化它,那这个类是什么呢?

这引出了我们这片文章的核心了:元类。

实例化出People这个类的类,就叫做元类。

在我们用class关键字定义People类的时候,其实在python解释器内部进行的操作是调用解释器默认的元类type来进行实例化:即People = type(),产生一个名叫People的对象,只不过这个对象有点特殊,它也是一个类,可以实例化对象。

当然,除了默认的元类,我们自己也可以创建元类,不过自建元类需要继承type类。

3.类对象的创建流程

为了理解类对象的创建流程,我们先看下面的一段代码:

print('创建我的元类:')
class MyMetaclass(type):      # 自建我们的自己的元类
    def __init__(self,name,bases,dict):
        print('init')
        super().__init__(name,bases,dict)
    def __call__(self, *args, **kwargs):
        print('call')
        return super().__call__(*args, **kwargs)
    def __new__(cls, *args, **kwargs):
        print('new')
        return super().__new__(cls, *args, **kwargs)
    pass

print('创建People类:')
class People(object,metaclass=MyMetaclass):        # 以MyMetaclass为元类创建一个类
    def __init__(self):
        print('sub_init')
        super().__init__()
    def __call__(self, *args, **kwargs):
        print('sub_call')
    def __new__(cls, *args, **kwargs):
        print('sub_new')
        return super().__new__(cls, *args, **kwargs)

他的输出结果是:

创建我的元类:
创建People类:
new
init

如上,我们可以知道,在创建类的时候,python解释器内部依次调用了元类内的__new__和__init__方法,通过查找资料可以知道:

1.__new__方法其实继承于python中默认基类object类,他的作用时新建一个空的对象=obj(这里我们为了便于叙述将其命名为obj),然后将obj传入__init__方法初始化,即obj.属性=你传入__init__的其他参数

2.需要注意的是,在如果一个类实例化的对象是类,__init__函数需要传入4个参数:self(这里就是__new__方法创建的空对象),classname(你想要创建的类的名字,用上面的例子来说就是People),classbases(你想要创建的类的基类,默认是object),classdict(你想要创建的类的名称空间,里面以字典形式保存了类的数据属性)

但是还没有结束,我们将上面的例子再扩展一下:

print('创建我的元类:')
class MyMetaclass(type):
    def __init__(self,name,bases,dict):
        print('init')
        super().__init__(name,bases,dict)
    def __call__(self, *args, **kwargs):
        print('call')
        return super().__call__(*args, **kwargs)
    def __new__(cls, *args, **kwargs):
        print('new')
        return super().__new__(cls, *args, **kwargs)
    pass

print('创建People类:')
class People(object,metaclass=MyMetaclass):
    def __init__(self):
        print('sub_init')
        super().__init__()
    def __call__(self, *args, **kwargs):
        print('sub_call')
    def __new__(cls, *args, **kwargs):
        print('sub_new')
        return super().__new__(cls, *args, **kwargs)

print('p1实例化后:')
p1 = People()
print('调用p1:')
p1()

它的输出结果是:

创建我的元类:
创建People类:
new
init
p1实例化后:
call
sub_new
sub_init
调用p1:
sub_call

从上面的结果可以看出,People类在实例化对象p1的时候, 会先调用元类MyMetaclass的__call__函数,然后再调用People类自己的__new__和__init__方法,而且后面调用p1的时候,也调用了People的__call__方法。

可见之前我们认为实例化对象的时候只调用类自己的__new__和__init__方法的结论并不完善。

结合上面的代码实验,我们可以基本看出python实例化对象的流程:

1.创建普通对象:在python中,调用一个类去实例化对象的时候,会先调用这个类的元类的__call__方法,在元类的__call__方法中,会先调用类自己的__new__方法创建空对象,然后用类自己的__init__方法初始化这个空对象,最后元类的__call__的方法将初始化后的对象返回,作为实例化结果赋值给你想赋值的对象。

2.创建类对象(类的创建流程):基本流程同第一点,需要注意的是:当调用的对象是元类的时候(即你想生成一个类),在用__init__函数初始化的时候,空对象作为__init__函数的第一个参数传入,【你想要创建的类的名字,你想要创建的类的基类,你想要创建的类的名称空间】作为必须的后三个参数传入__init__函数,最后元类的__call__的方法将初始化后的对象返回,即你创建了一个类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值