Python 元类与x27的关系;s"__打电话给;和实例';s"__初始化;?

Python 元类与x27的关系;s"__打电话给;和实例';s"__初始化;?,python,metaclass,Python,Metaclass,假设我有一个元类和一个使用它的类: class Meta(type): def __call__(cls, *args): print "Meta: __call__ with", args class ProductClass(object): __metaclass__ = Meta def __init__(self, *args): print "ProductClass: __init__ with", args p = P

假设我有一个元类和一个使用它的类:

class Meta(type):
    def __call__(cls, *args):
        print "Meta: __call__ with", args

class ProductClass(object):
    __metaclass__ = Meta

    def __init__(self, *args):
        print "ProductClass: __init__ with", args

p = ProductClass(1)
输出如下:

Meta:\uuuuu调用\uuuuu与(1,)
问题:

为什么
ProductClass.\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
没有被触发…仅仅是因为
Meta.\uuuuuuuuuuuuu

更新:

现在,我为ProductClass添加了
\uuuuu new\uuuuu

class ProductClass(object):
    __metaclass__ = Meta

    def __new__(cls, *args):
        print "ProductClass: __new__ with", args
        return super(ProductClass, cls).__new__(cls, *args)

    def __init__(self, *args):
        print "ProductClass: __init__ with", args

p = ProductClass(1)

调用ProductClass的
\uuuuuuuuuuu新的
\uuuuuuuuuuuu和
\uuuuuuuu初始是否是
.uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

引述:

例如,在元类中定义一个自定义的
\uuuuu调用
方法 在调用类时允许自定义行为,例如不总是 创建一个新实例


该页面还提到了一个场景,其中元类的
\uuuu调用
可能返回不同类的实例(即,在您的示例中不是
ProductClass
)。在这种情况下,显然不适合自动调用
ProductClass.\uuuu init\uuuu

在OOP中,扩展方法和重写方法之间存在差异,您刚才在元类
Meta
中所做的操作被称为重写,因为您定义了
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu方法,而没有调用父类
\uuuuuuuuuuuuu。要获得所需的行为,您必须通过调用父方法来扩展
\uuuuu call\uuuu
方法:

class Meta(type):
    def __call__(cls, *args):
        print "Meta: __call__ with", args
        return super(Meta, cls).__call__(*args)

如果我在ProductClass中得到一个“新”怎么办?Meta的“调用”会调用ProductClass的“新建”和“初始化”吗?请参阅我的更新。显然,Meta的“调用”是在ProductClass的“新建”之前先调用的。问题是
Meta.\uu call\uuuuuu
必须调用
ProductClass.\uuu new\uuuuuu
ProductClass.\uuu init\uuuuu
。通常,
type.\uuuuu-call\uuuu
会为您执行此操作,但当您定义
Meta.\uuuuuu-call\uuuu
时,您会覆盖该行为,这意味着除非您这样做,否则不会执行该行为。因此,您需要自己调用
\uuuuu new\uuuu
\uuuu init\uuuu
或者调用类似于
类型的东西。它需要返回它作为第一个参数传递的类的实例
cls
。这通常是通过在其父类(也称为基类)中调用同名的方法来实现的。这可以通过硬编码来实现,即
返回类型。
或使用
返回超级(Meta,cls)。\u调用(*args)