Python 中的元类:需要澄清的几个问题
在与元类崩溃之后,我深入研究了 Python 中的元编程主题,恕我直言,我有几个问题在可用文档中没有明确回答。
- 在元类中同时使用 __new__ 和 __init__ 时,它们的参数必须定义相同吗?
- 在元类中定义类
__init__
的最有效方法是什么? - 有没有办法在元类中引用类实例(通常是self)?
After crashing with metaclasses i delved into the topic of metaprogramming in Python and I have a couple of questions that are, imho, not clearly anwered in available docs.
- When using both
__new__
and__init__
in a metaclass, their arguments must be defined the same? - What's most efficient way to define class
__init__
in a metaclass? - Is there any way to refer to class instance (normally self) in a metaclass?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
同时使用
__new__
和__init__
时在元类中,它们的参数必须
定义相同吗?
我认为Alex Martelli解释了
最简洁地说:
表示
所以别再想了
合适的元类作为元类
暂时将其视为
班级。每当你看到
它告诉你
合适的_metaclass的
__new__
方法必须有签名
类似的东西
和一个
__init__
方法,例如因此签名并不完全相同,但它们仅在第一个参数上有所不同。
最有效的定义方式是什么
元类中的类
__init__
?高效是什么意思?这是
不需要定义
__init__
除非你愿意。
有没有办法引用类
实例(通常是自身)
元类?
不,您不需要这样做。
任何取决于班级的事情
实例应在
类定义,而不是在
元类。
When using both
__new__
and__init__
in a metaclass, their arguments must
be defined the same?
I think Alex Martelli explains
it most succinctly:
means
So stop thinking about
suitable_metaclass as a metaclass
for a moment and just regard it as a
class. Whenever you see
it tells you that
suitable_metaclass's
__new__
method must have a signature
something like
and a
__init__
method likeSo the signatures are not exactly the same, but they differ only in the first argument.
What's most efficient way to define
class
__init__
in a metaclass?What do you mean by efficient? It is
not necessary to define the
__init__
unless you want to.
Is there any way to refer to class
instance (normally self) in a
metaclass?
No, and you should not need to.
Anything that depends on the class
instance should be dealt with in the
class definition, rather than in the
metaclass.
对于 1:any 类的
__init__
和__new__
必须接受相同的参数,因为它们将使用相同的参数进行调用。__new__
通常会接受更多它忽略的参数(例如object.__new__
接受任何参数并忽略它们),因此__new__
不会'在继承过程中不必重写,但通常只有在根本没有 __new__ 时才这样做。这在这里不是问题,因为正如前面所说,元类总是使用相同的参数集来调用,因此您不会遇到麻烦。至少有论据。但是,如果您要修改传递给父类的参数,则需要同时修改它们。
对于2:您通常不会在元类中定义类
__init__
。您可以编写一个包装器并在元类的__new__
或__init__
中替换该类的__init__
,也可以重新定义元类上的 __call__
。如果您使用继承,前者会表现得很奇怪。调用它的结果:
对于 3:是的,来自
__call__
,如上所示。For 1: The
__init__
and__new__
of any class have to accept the same arguments, because they would be called with the same arguments. It's common for__new__
to take more arguments that it ignores (e.g.object.__new__
takes any arguments and it ignores them) so that__new__
doesn't have to be overridden during inheritance, but you usually only do that when you have no__new__
at all.This isn't a problem here, because as it was stated, metaclasses are always called with the same set of arguments always so you can't run into trouble. With the arguments at least. But if you're modifying the arguments that are passed to the parent class, you need to modify them in both.
For 2: You usually don't define the class
__init__
in a metaclass. You can write a wrapper and replace the__init__
of the class in either__new__
or__init__
of the metaclass, or you can redefine the__call__
on the metaclass. The former would act weirdly if you use inheritance.And the result from calling it:
For 3: Yes, from
__call__
as shown above.