使用Metaclass的动态类定义
我试图动态创建类定义,如下所示。
class SomeMetaclass(type):
def __new__(cls, clsname, bases, clsdict):
print("Using this metaclass")
return super().__new__(cls, clsname, bases, clsdict)
SomeClassFoo = SomeMetaclass('SomeClassFoo', (), {})
# Similar to the following
# SomeClassFoo = type('SomeClassFoo', (), {})
但是,我认为我在这里错过了一些东西。虽然上面的示例无法做我期望的事情,但以下方法有效:
class SomeClassBar(metaclass=SomeMetaclass):
pass
但是,当我在两个示例中运行type(someclassfoo)
时,我都会得到类somemetaclass ?
# The following statement is true
type(SomeClassFoo) is type(SomeClassBar)
准备/新的方法在使用前一个方法定义类时未调用?
I am trying to create class definitions dynamically as follows.
class SomeMetaclass(type):
def __new__(cls, clsname, bases, clsdict):
print("Using this metaclass")
return super().__new__(cls, clsname, bases, clsdict)
SomeClassFoo = SomeMetaclass('SomeClassFoo', (), {})
# Similar to the following
# SomeClassFoo = type('SomeClassFoo', (), {})
However, I think I am missing something here. While the above example doesn't do what I would expect it to, the following method works:
class SomeClassBar(metaclass=SomeMetaclass):
pass
However, when I run type(SomeClassFoo)
in both the examples, I get class SomeMetaclass
?
# The following statement is true
type(SomeClassFoo) is type(SomeClassBar)
Are the prepare/new methods not called when the class is defined using the former method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
所有人都按预期工作。问题当前被认为是低质量,因为您可能忘记在摘要上放置
__准备__
实现,但是从评论中,我想您正在做类似的事情:运行它,输出为::
正如这里可见的那样,“ someclass1”创建不调用
__准备__
,正确:类名称空间已经传递到呼叫中,为第三个参数,{}
,没有身体要跑。当一个人想以这样的程序方式使用元类(包括允许Python使用内部查找机制来获取正确的
__准备__
方法,并手动使用它,types 那。有两种方式,一个正在打电话
types.prepare_class
它将找出要调用的正确元类(如果除了您的显式“ Metaclass”参数外,您的“基础”还包括也具有元元素的类,一个要呼叫的元素是最派生的元类)) ,运行其__准备__
方法,然后返回元素,由__准备__
创建的命名空间以及任何剩余的关键字参数以调用元素。然后,您可以在看到合适的情况下调用返回的元素:(请注意,如果您想要的东西,则应该在两个呼叫之间填充“ classDict”)。
另一种方法是调用
types.new_class
:它几乎可以做到这一点,但是它不会为您返回类创建信息,而是将metaclass .__新的__ new __
直接调用。如果要将任何内容插入新的类名称空间中,则必须将其传递给第四个参数,并带有一个回调,将其命名空间作为参数,它必须填充它并将其返回:All is working as expected. The question is currently regarded as low quality, as you likely forgot to put
__prepare__
implementation on your snippets, but from the comments, I imagine you are doing something like this:Upon running it, the output is:
As is visible here, "SomeClass1" creation does not call
__prepare__
, rightly: the class namespace is already passed into the call as the third parameter which is{}
, and there is no body to be run.When one wants to use metaclasses in a programatic way like this, including allowing Python to use the internal lookup mechanisms to get the correct
__prepare__
method, and use it manually, there are helpers in thetypes
module that provide the means for that. There are two ways, one is callingtypes.prepare_class
which will find out the correct metaclass to call (if besides your explicit "metaclass" parameter, your "bases" include classes which also have metaclasses, the one to call is the most derived metaclass), run its__prepare__
method, and return you the metaclass, the namespace created by__prepare__
and any remainder keyword arguments to call the metaclass. You can then call the returned metaclass as you see fit:(note that between both calls you are supposed to populate "classdict" if you want something in there).
The other way is to call
types.new_class
: it does almost the samething, but instead of returning the class creation information for you, it will call themetaclass.__new__
method directly. If you want to insert anything into the new class namespace, you have to pass it a 4th parameter, with a callback that will take the namespace as a parameter, it has to populate it, and return it: