【问题标题】:Extra arguments in Metaclass元类中的额外参数
【发布时间】:2014-12-21 16:13:40
【问题描述】:

我写了以下元类:

class FieldHandlerBase(type):
    def __new__(cls, name, bases, dct, model):
        ...
        return super(FieldHandlerBase, cls).__new__(cls, name, bases, dct)

现在,我尝试使用上述元类动态创建一个类:

FieldHandlerBase(
    '%sFieldHandler' % name,
    (FieldHandler,),
    {rel_type: dct.setdefault(rel_type, ()) for rel_type in REL_TYPES},
    model=name)

但它抛出了这个错误:

>           model=name)
E       TypeError: Error when calling the metaclass bases
E           type.__init__() takes no keyword arguments

我不明白为什么,因为我使用正确数量的参数调用元类基础(此处为type,来自FieldHandlerBase)。我怎样才能解决这个问题?我需要将一个额外的参数传递给FieldHandlerBase,并且我不想将它包含在dct 参数中,因为我只在元类级别需要它。

【问题讨论】:

    标签: python metaprogramming metaclass


    【解决方案1】:

    您需要编写一个__init__ 方法以及一个__new__ 方法。否则,python 将为你的新类调用 type.__init__,它不接受任何额外的参数。

    例如。

    class FieldHandlerBase(type):
    
        def __init__(cls, name, bases, attrs, model):
            type.__init__(cls, name, bases, attrs)
            cls.model = model
    
        def __new__(metacls, name, bases, attrs, model):
            ...
            return type.__new__(metacls, name, bases, attrs)
    
    class ExampleFieldHandler(FieldHandler, metaclass=FieldHandlerBase, 
            model="Example"):
        clsvar = "var"
    
    # or 
    ExampleFieldHandler = FieldHandlerBase(
        "ExampleFieldHandler",
        (FieldHandler,),
        {"clsvar": "var"},
        model="Example"
    )
    
    assert ExampleFieldHandler.model == "Example"
    

    【讨论】:

    • 哦,我以为__init__() 将使用与__new__() 相同的参数来调用。谢谢!
    • 是的。这就是问题所在。由于您尚未定义自己的__init__,因此调用了超类(类型)上的__init____init__ on 类型不接受模型作为参数,因此调用失败。
    • 我指的是__new__() 的第二次调用,这是我对超类 (type) 的调用,并且我精确地省略了 model 参数。但如果我理解正确,对__new__()__init__() 的调用是从其他地方发送的,无论我在这两种方法中做什么,它们都有相同的参数。现在,出于好奇,究竟是谁将调用发送到__new__()__init__()
    • 没错。 type 实现了__call__,它调度了这两个调用。您可以通过type.__call__(YourMetaclass, names, bases, attrs, yourargs) 进行检查
    猜你喜欢
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2011-06-25
    • 2023-03-12
    • 2020-06-10
    • 2016-01-20
    相关资源
    最近更新 更多