【问题标题】:Why is the argument passed to __getattribute__ not recognized?为什么传递给 __getattribute__ 的参数无法识别?
【发布时间】:2017-08-10 00:03:00
【问题描述】:

一个非常基本的问题。

我有一些虚拟课程:

class SomeClass:
    """ just a docstring"""

    a = 5

dir(SomeClass),返回与该类关联的以下属性:

>>> dir(SomeClass)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__form
at__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_s
ubclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
 '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclas
shook__', '__weakref__', 'a']
>>>

我注意到,如果我调用 SomeClass.__getattribute__,即使我向它传递了一个参数(它说它需要),错误消息说我没有传递任何参数。

>>> SomeClass.__getattribute__('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected 1 arguments, got 0
>>>

注意 - 并不是我想要以这种方式调用 __getattribute__ 的用例。 (实际上这样做似乎不正确,我想在实例上调用它取而代之的是 SomeClass ,它确实有效)。 我只是对 __getattribute__ 的行为感到好奇:为什么错误消息说它有 0 个参数,而我实际上是在向它传递一个参数?我并不否认我的用法不正确 -只是,为什么 __getattribute__ 不承认它被传递了一个参数?

我确实注意到 __getattribute__ 被列为“slotwrapper”。这有关系吗?我很难弄清楚调用 slotwrapper 和调用函数之间的真正区别是什么。这个 slotwrapper 是否因为我调用它的方式而抛弃了我传递的参数?

>>> SomeClass.__getattribute__
<slot wrapper '__getattribute__' of 'object' objects>
>>>

【问题讨论】:

    标签: python-3.x function getattribute


    【解决方案1】:

    您正在调用的函数__getattribute__ 是一个方法。它需要 两个 参数。第一个参数是self,它通常是SomeClass 的一个实例(并且通常在您通过实例调用时自动提供:instance.__getattribute__)。第二个参数是要查找的属性的名称。

    当您调用SomeClass.__getattribute__("a") 时,您将"a" 传递为self。这不是一件非常有用的事情。如果你也提供了第二个参数,它甚至可能会起作用(因为SomeClass.__getattribute__ 继承自objectstr.__getattribute__ 也是如此)。它将查找您传入的字符串的属性,而不是与 SomeClass 相关的任何内容。

    唯一奇怪的行为是它说得到零个参数(并且期望一个),而不是说它得到一个参数并期望两个。 部分问题可能是一个(小)错误。

    【讨论】:

    • 非常感谢您的解释。我对错误消息本身感到非常困惑。 _setattr_ 有类似的问题,如果我在调用这种(不正确的)方式时传递了两个参数,错误消息说它需要 2 个参数但只收到 1 个。(似乎它真的应该期待虽然有 3 个参数 - 实例、要设置的属性的名称以及要设置的值)。
    • 我怀疑虚假错误消息是因为这些是用 C 编写的方法(您从 object 继承)。内置方法有点奇怪。如果你用 Python 编写了自己的方法,如果调用不正确,它会给出适当的错误消息。
    【解决方案2】:

    你也可以试试getattr(SomeClass, "a")。在类似的情况下,这对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      • 1970-01-01
      • 2019-08-07
      • 2020-02-12
      • 2014-12-30
      • 1970-01-01
      相关资源
      最近更新 更多