【问题标题】:python: how to access attributes of functionspython:如何访问函数的属性
【发布时间】:2012-07-27 15:16:32
【问题描述】:

我正在尝试访问成员函数的属性,但我不明白为什么我只能通过__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?

【问题讨论】:

  • 您正试图在类定义中的方法上添加属性?
  • 你到底为什么想要这个?
  • 我想要这个,因为它是一个 python 功能。一开始,当我希望派生类设置其方法之一的属性时,我做了类似的事情。我需要正确的答案。
  • 是的,我正在尝试添加属性。但我更关心的是了解语言是如何工作的。我知道这很容易成为不好的做法。

标签: python lookup member-functions


【解决方案1】:

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

【讨论】:

  • 这就是我想要的答案。你能告诉我在哪里可以阅读更多吗?我也想知道什么是非标准属性。没有人告诉我这个概念!
  • 该链接表明它不是一定数量的属性。而是无法在绑定或未绑定的方法上执行此操作。
  • instancemethod 是一个在 C 中作为 CPython 实现的一部分实现的类。因此,它没有普通 Python 对象所具有的内置灵活性。它确实有一个 __dict__(因为 C 实现提供了它),但它的 __getattribute__ 不会自动映射到该字典中的内容。
【解决方案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 function attributes - uses and abuses

【讨论】:

    猜你喜欢
    • 2011-03-07
    • 2011-11-05
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    • 2018-06-03
    • 1970-01-01
    • 2019-02-11
    相关资源
    最近更新 更多