我目前有这段代码:
class Generator(object):
def __getattr__(self, name):
def f(self):
return ("Result of"+name, self)
f.__name__ = name
return f
def foo(self):
pass
g = Generator()
print g.foo
print Generator.foo
print g.bar
print Generator.bar
给出:
<bound method Generator.foo of <__main__.Generator object at 0x00B62D30>>
<unbound method Generator.foo>
<function bar at 0x00A9DE70>
AttributeError: type object 'Generator' has no attribute 'bar'
我必须做什么才能让它给出:
<bound method Generator.foo of <__main__.Generator object at 0x00B62D30>>
<unbound method Generator.foo>
<bound method Generator.bar of <__main__.Generator object at 0x00B62D30>>
<unbound method Generator.bar>
请您参考如下方法:
这是一个元类,它将类定义中的 __getattr__ 函数添加回元类本身。这避免了必须在多个地方定义函数,或者作为一个单独的全局函数预先定义并单独添加到元类和类中。
class Meta(type):
def __new__(mcls, name, bases, dikt):
fgetattr = dikt.get('__getattr__')
if fgetattr is not None:
setattr(mcls, '__getattr__', fgetattr)
return super(Meta, mcls).__new__(mcls, name, bases, dikt)
class Generator(object):
__metaclass__ = Meta
def __getattr__(obj, name):
def f(self):
return "Result of %s for %r" % (name, self)
f.__name__ = name
if isinstance(obj, type):
setattr(obj, name, f)
else:
setattr(type(obj), name, f)
return getattr(obj, name)
与其直接通过动态函数的__get__ 描述符方法创建方法,我认为最好将函数存储在类dict 中并依靠getattr 返回正确的绑定(bind)/未绑定(bind)方法。随后的属性访问将使用类中的函数。由于相同的 __getattr__ 函数同时用于类和实例,因此需要进行 isinstance 检查以确保将动态函数存储到类而不是实例。
在 Python 3 中,将函数作为类的属性获取仅返回函数,因为从语言中删除了未绑定(bind)的方法。此外,metaclass syntax已更改为类定义行中的关键字参数。
测试:
>>> g = Generator()
>>> g.foo
<bound method Generator.foo of <__main__.Generator object at 0xb7248c2c>>
>>> Generator.foo
<unbound method Generator.foo>
>>> g.bar
<bound method Generator.bar of <__main__.Generator object at 0xb7248c2c>>
>>> Generator.bar
<unbound method Generator.bar>
>>> g.foo()
'Result of foo for <__main__.Generator object at 0xb7248c2c>'
>>> Generator.foo(g)
'Result of foo for <__main__.Generator object at 0xb7248c2c>'
>>> 'foo' in vars(Generator), 'bar' in vars(Generator)
(True, True)
