06-metaclass

基于类创建对象回顾

class Foo(object):

    def __init__(self,name):
        self.name=name
        print('__init__执行')

    def __new__(cls,*args,**kwargs):
        data=object.__new__(cls)
        print('__new__执行')
        return data


# 根据类创建对象
# 1. 先执行类的new方法,创建一个空对象
# 2. 执行类的init方法放入数据
obj=Foo("武沛齐")

对象是基于类创建的。

问题:类是由谁创建的?类默认是由type创建的

# 传统的创建类的方式
class Foo(object):
    v1 = 123

    def func(self):
        return 666


obj=Foo()
print('Foo类属于:',Foo.__class__)
print('obj属于:',obj.__class__)


# 输出
Foo类属于: <class 'type'>
obj属于: <class '__main__.Foo'>
# 非传统方式
Foo = type("Foo", (object, ), {"v1": 123, "func": lambda self: 666})


obj=Foo()
print('Foo类属于:',Foo.__class__)
print('obj属于:',obj.__class__)


# 输出
Foo类属于: <class 'type'>
obj属于: <class '__main__.Foo'>

第二种创建方式中"Foo"表示类名,(object,)表示继承关系,{"v1": 123, "func": lambda self: 666}表示给Foo这个类指定了两个属性,一个是"v1": 123,一个是"func": lambda self: 666

元类

类默认由type创建,怎么让一个类的创建改成其他的东西?元类,指定类由谁来创建。

# type创建Foo类型
class Foo(object):
    pass
# `东西`创建Foo类型
class Foo(object,metaclass=东西):
    pass
class MyType(type):

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

    def __new__(cls, *args, **kwargs):
        print("new")
        new_cls = super().__new__(cls, *args, **kwargs)
        return new_cls


class Foo(object, metaclass=MyType):
    pass

在这里,MyType就好比以前我们学习的类,Foo就好比我们以前学的对象,通过类来创建对象,先执行new,再执行init,在这里,通过MyType来创建Foo这个类,也是如此

call

class F1(object):

    def __call__(self,*args,**kwargs):
        print("__call__")

f1=F1()
f1()

对象()会触发call方法的执行,那么我们知道类相当于对象,type相当于类,也就是说,类()是否会触发type的__call__的执行呢?

class MyType(type):

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

    def __new__(cls, *args, **kwargs):
        print("new")
        new_cls = super().__new__(cls, *args, **kwargs)
        return new_cls

    def __call__(self, *args, **kwds):
        print("__call__")
        return super().__call__(*args, **kwds)


class Foo(object, metaclass=MyType):
    pass


v1=Foo()

# 输出
new
init
__call__
posted @   yaowy  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示