问题描述
说有:
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 动态类方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!