Python动态类方法

Eci*_*ana 4 python runtime class-method

说有:

class A(B):
    ...
Run Code Online (Sandbox Code Playgroud)

这里B可能是object...不是:

@classmethod # or @staticmethod
def c(cls): print 'Hello from c!'
Run Code Online (Sandbox Code Playgroud)

我不得不做什么叫A.c()不会触发AttributeError

换句话说,我知道可以在运行时手动将类方法添加到类中.但是有可能自动这样做,比如每次缺少类方法时都会创建一些虚拟方法吗?

换句话说,只有我可以A.__dict__用我的dict 替换处理__getitem__- 但A.__dict__似乎不可写......

Mar*_*ers 13

您可以通过在元类上使用__getattr__钩子来实现此目的.

class DefaultClassMethods(type):
    def __getattr__(cls, attr):
        def _defaultClassMethod(cls):
            print 'Hi, I am the default class method!'
        setattr(cls, attr, classmethod(_defaultClassMethod))
        return getattr(cls, attr)
Run Code Online (Sandbox Code Playgroud)

演示:

>>> class DefaultClassMethods(type):
...     def __getattr__(cls, attr):
...         def _defaultClassMethod(cls):
...             print 'Hi, I am the default class method!'
...         setattr(cls, attr, classmethod(_defaultClassMethod))
...         return getattr(cls, attr)
... 
>>> class A(object):
...     __metaclass__ = DefaultClassMethods
... 
>>> A.spam
<bound method DefaultClassMethods._defaultClassMethod of <class '__main__.A'>>
>>> A.spam()
Hi, I am the default class method!
Run Code Online (Sandbox Code Playgroud)

请注意,我们将classmethod调用的结果直接设置到类上,有效地将其缓存以供将来查找.

如果需要在每次调用时重新生成类方法,请使用相同的方法将函数绑定到实例,但使用类和元类(使用cls.__metaclass__与元类子类一致):

from types import MethodType

class DefaultClassMethods(type):
    def __getattr__(cls, attr):
        def _defaultClassMethod(cls):
            print 'Hi, I am the default class method!'
        return _defaultClassMethod.__get__(cls, cls.__metaclass__)
Run Code Online (Sandbox Code Playgroud)

对于静态方法,只需在所有情况下直接返回函数,不需要使用staticmethod装饰器或描述符协议.