Python动态类方法

标签 python runtime class-method

假设有:

class A(B):
    ...

其中 B 可以是 object...不是:

@classmethod # or @staticmethod
def c(cls): print 'Hello from c!'

我该怎么做才能调用 A.c() 不会触发 AttributeError

换句话说,我知道可以在运行时手动将类方法添加到类中。但是是否可以自动执行此操作,比如每次缺少类方法时都会创建一些虚拟方法?

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

最佳答案

您可以使用 __getattr__ hook 来实现此目的在 metaclass 上.

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 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!

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

如果您需要在每次调用时重新生成类方法,请使用相同的 method to bind a function to an instance但是用类和元类代替(使用 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__)

对于静态方法,在所有情况下都直接返回函数,无需使用 staticmethod 装饰器或描述符协议(protocol)。

关于Python动态类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11281698/

相关文章:

java - 通过java运行批处理文件

ruby - YARD:记录由包含的模块添加的类方法

c - 变量初始化计算结果出乎意料

ruby-on-rails - 在 Ruby 中将排序实现为类方法

python - 为什么类变量可以通过类实例访问?

Python - 尝试在 IF 语句中使用列表值

python - 使用 Bokeh 绘制条形图

python - 我应该直接返回数据集还是应该使用 one_shot 迭代器?

python - 日志记录在单独的线程中不起作用

c++ - 只在运行时知道数据类型。如何向使用它们的其他类隐藏数据详细信息