在功能定义__getattr__和__getitem__没有影响(Defining __getatt

2019-09-17 14:42发布

免责声明这仅仅是在元编程练习,它没有实际用途。

我已经指派__getitem____getattr__函数对象的方法,但没有效果...

def foo():
  print "foo!"

foo.__getitem__ = lambda name: name
foo.__getattr__ = lambda name: name
foo.baz = 'baz'

仔细的检查,我们可以分配属性的功能:

>>> foo.baz
'baz'

整齐。 如何“神奇干将”?

>>> foo.bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'bar'

是否有可能有一个“神奇的getter”函数对象?

Answer 1:

不! 分配__getitem__到实例上的任何类型的对象不起作用:

>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'foo'

不能定义__getattr__在内置函数类型:

>>> import types
>>> types.FunctionType.__getitem__ = lambda name: name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'function'

而且你不能继承types.FunctionType

>>> import types
>>> class F(types.FunctionType):
...   pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
type 'function' is not an acceptable base type


Answer 2:

至少在新的样式类(这是唯一的一种在Python 3,你应该在Python 2使用的那种),巨蟒仅查找魔术方法的类(和它的祖先),从来没有在该实例。 这里的文档 。

当然,你不能修改函数类型,或者从它派生。 正如您看到的,但是,与任何类__call__()方法使可调用的情况下,所以这是做到这一点的方式。



Answer 3:

AHHA! 使用__call__ ,并包裹在函数F()

class F(object):
    def __init__(self, fn):
        self.__dict__['fn'] = fn

    def __call__(self, *args, **kwargs):
        return self.fn(*args, **kwargs)

    def __getitem__(self, name):
        return name

    def __getattr__(self, name):
        return name

>>> foo = F(foo)
>>> f.bar
'bar'
>>> f['foo']
'foo'
>>> foo()
foo!


文章来源: Defining __getattr__ and __getitem__ on a function has no effect