有没有办法编写一个元类,使得基于这个元类的类中定义的所有方法默认都是类方法(即不需要,例如@classmethod
装饰等)?
谢谢!
编辑:我对 Python 2.7.3 感兴趣。请原谅遗漏。
有没有办法编写一个元类,使得基于这个元类的类中定义的所有方法默认都是类方法(即不需要,例如@classmethod
装饰等)?
谢谢!
编辑:我对 Python 2.7.3 感兴趣。请原谅遗漏。
当然。真正的问题是你为什么要这样做。我将假设这仅用于教育。实际上,无论这可以用于什么,都可能最好明确地完成(即不使用元类并添加@classmethod
)。
我知道两个选项:类定义的自定义命名空间和__new__
. 第一个非常酷,在某些情况下实际上是不可避免的(例如记住方法定义的顺序),但后者更简单、更灵活,不会意外破坏同名的多个赋值,并且在 Python 2 中可用。你的目的,这排除了前者,但我会把它留给所有可以使用 Python 3 的人。
要提供自定义命名空间,您必须__prepare__
在元类中定义并返回类似字典的对象(Ferdinand Beyer 在评论中指出:定义的映射接口collections
就足够了)。在这种情况下,字典应该重写__setitem__
以检查值是否为callable
,如果是,则在classmethod
存储之前将其包装起来。我非常感谢下面的评论,他们极大地改进了下面的代码。Ferdinand Beyer 注意到这callable(classmethod(...))
是错误的,并且 agf 指出了与@classmethod
Python 3 兼容性的不一致之处。
import types
# Either this, in a dictionary class instanciated in __prepare__
# Again, Python 3 only
def __setitem__(self, name, value):
if isinstance(value, types.FunctionType):
value = classmethod(value)
super().__setitem__(name, value)
# __prepare__ would be: return AutomaticClassMethodNamespace() or something
# Or this in the metaclass
def __new__(mcls, clsname, bases, ns):
for name, value in ns.items():
if isinstance(value, types.FunctionType):
ns[name] = classmethod(value)
# Any other metaclass behaviour
像这样的东西(2.7)
def m(name, bases, dct):
for k, v in dct.items():
if type(v) is type(m):
dct[k] = classmethod(v)
return type(name, bases, dct)
class A:
__metaclass__ = m
def foo(self):
print self
A.foo() # <class '__main__.A'>