本文介绍了Python 动态类方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说有:

A(B)类:...

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

@classmethod # 或 @staticmethoddef c(cls): 打印 'Hello from c!'

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

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

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

解决方案

您可以通过使用 __getattr__ hook元类.

class DefaultClassMethods(type):def __getattr__(cls, attr):def _defaultClassMethod(cls):打印我是默认的类方法!"setattr(cls, attr, classmethod(_defaultClassMethod))返回 getattr(cls, attr)

演示:

>>>类 DefaultClassMethods(类型):... def __getattr__(cls, attr):... def _defaultClassMethod(cls):...打印'我是默认的类方法!'... setattr(cls, attr, classmethod(_defaultClassMethod))...返回 getattr(cls, attr)...>>>A类(对象):... __metaclass__ = DefaultClassMethods...>>>垃圾邮件<绑定方法 DefaultClassMethods._defaultClassMethod of <class '__main__.A'>>>>>A.垃圾邮件()我是默认的类方法!

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

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

from types import MethodType类 DefaultClassMethods(类型):def __getattr__(cls, attr):def _defaultClassMethod(cls):打印我是默认的类方法!"返回 _defaultClassMethod.__get__(cls, cls.__metaclass__)

对于静态方法,在所有情况下都直接返回函数,无需与 staticmethod 装饰器或描述符协议混在一起.

Say there is:

class A(B):
    ...

where B could be object and ... is not:

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

What do I have to do that calling A.c() wont trigger AttributeError?

In other words, I know it is possible to manually add class methods to a class at runtime. But is it possible to do so automatically, say every time a class method is missing it creates some dummy method?

In yet another words, only if I could replace A.__dict__ with my dict which handles __getitem__ - but A.__dict__ seems to be not writable...

解决方案

You can achieve this by using a __getattr__ hook on a 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)

Demo:

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

Note that we set the result of the classmethod call straight onto the class, effectively caching it for future lookups.

If you need to regenerate the class method on every call instead, use the same method to bind a function to an instance but with the class and metaclass instead (using cls.__metaclass__ to be consistent with metaclass subclassing):

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__)

For static methods just return the function directly in all cases, no need to muck with the staticmethod decorator or the descriptor protocol.

这篇关于Python 动态类方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 20:25
查看更多