是否有办法编写元类,以便默认情况下基于此元类的类中定义的所有方法都是类方法(即不需要,例如@classmethod
装饰等)?
谢谢!
编辑:我对Python 2.7.3很感兴趣。请原谅这个遗漏。
答案 0 :(得分: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
答案 1 :(得分:0)
像这样(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'>