2

我正在尝试访问成员函数的属性,但我不明白为什么我只能通过__dict__.

class A(object):
    def fA(self):
        print A.fA.x 
    fA.x = 2

A.fA.__dict__['x'] = 3 
#A.fa.x #AttributeError: 'instancemethod' object has no attribute 'x'
A.fA.x = 4 

如果我尝试“直接”访问,为什么会收到 AttributeError?

4

2 回答 2

3

因为instancemethod对象是如何实现的。他们使用不允许访问非标准属性的非标准属性获取器。

于 2012-07-29T22:01:05.843 回答
2

不知道你为什么会这样做,但是......

A.fA 实际上是与函数 fA 完全分离的对象。手表:

>>> class A(object):
...   def fA(self): pass
...   print fA
... 
<function fA at 0x10f1c2a28>
>>> A.fA
<unbound method A.fA>

如您所见,A.fA 是“未绑定方法”,而不是函数。“未绑定”表示它不与任何实例关联;而绑定方法与特定实例相关联。观察:

>>> A().fA
<bound method A.fA of <__main__.A object at 0x10f1d3d10>>

无论哪种方式,方法都会包装实现它们的函数:

>>> A.fA.im_func
<function fA at 0x10f1c2a28>

请注意,地址与之前打印的地址相同。

奇怪的是,我无法重现您看到的行为:

>>> A.fA.__dict__['x'] = 1
>>> A.fA.x
1

也许,这种差异是由于不同版本的python造成的。这是我的:

$ python
Python 2.7.2 (default, Jun 20 2012, 16:23:33) 
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 

PS:A.fA.x 似乎和 A.fA.im_func.x 一样对我有用,这让我感到惊讶......再次,我有点怀疑你为什么要考虑这样做。通常,您唯一使用的时间__dict__是您正在实施__getattr__(不要与 混淆__getattribute__)。

赋予对象(尤其是基本类型的对象)即席属性也是一个好主意,这种情况也很少见。通常可行的替代方法是使用您自己的地图,例如

>>> def foo(): pass
... 
>>> my_x_values = {foo: 'X'}
>>> my_x_values[foo]
'X'

不过,并非所有人都同意这一点。查看另一个 SO 问题:Python 函数属性 - 使用和滥用

于 2012-11-27T06:48:20.877 回答