Metaclass使类方法成为默认值?

时间:2012-05-08 17:12:07

标签: python metaclass class-method

是否有办法编写元类,以便默认情况下基于此元类的类中定义的所有方法都是类方法(即不需要,例如@classmethod装饰等)?

谢谢!

编辑:我对Python 2.7.3很感兴趣。请原谅这个遗漏。

2 个答案:

答案 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'>