Почему аргумент, переданный в __getattribute__, не распознается?

Очень простой вопрос.

У меня есть фиктивный класс:

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». Это имеет отношение к этому? Мне трудно понять, в чем реальная разница между вызовом слот-обертки и вызовом функции. Отбрасывает ли этот слот-упаковщик аргумент, который я ему передал, из-за того, как я его назвал?

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

person ffConundrums    schedule 10.08.2017    source источник


Ответы (2)


Функция __getattribute__, которую вы вызываете, является методом. Он ожидает два аргумента. Первый аргумент — self, который обычно является экземпляром SomeClass (и обычно предоставляется автоматически, когда вы вызываете через экземпляр: instance.__getattribute__). Второй аргумент — это имя атрибута для поиска.

Когда вы вызываете SomeClass.__getattribute__("a"), вы передаете "a" как self. Это не очень полезное занятие. Если вы также предоставили второй аргумент, это может даже сработать (поскольку SomeClass.__getattribute__ наследуется от object, как и str.__getattribute__). Однако он будет искать атрибуты строки, которую вы передаете, а не что-либо, связанное с SomeClass.

Единственное странное поведение заключается в том, что он говорит, что получил ноль аргументов (и ожидал один), а не говорил, что он получил один аргумент и ожидал два. Эта часть проблемы может быть (незначительной) ошибкой.

person Blckknght    schedule 10.08.2017
comment
Большое спасибо за объяснение. Меня очень смутило само сообщение об ошибке. Это аналогичная проблема с _setattr_, если я передам ему два аргумента при вызове этим (неправильным) способом, в сообщении об ошибке говорится, что он ожидает 2 аргумента, но получил только 1. (Кажется, он действительно должен ожидать 3 аргумента — экземпляр, имя атрибута, который вы хотите установить, и значение, которое нужно установить). - person ffConundrums; 10.08.2017
comment
Я подозреваю, что фиктивные сообщения об ошибках связаны с тем, что это методы, написанные на C (которые вы наследуете от object). Встроенные методы немного странные. Если бы вы написали свой собственный метод на Python, он выдал бы соответствующее сообщение об ошибке при неправильном вызове. - person Blckknght; 10.08.2017

Вы также можете попробовать getattr(SomeClass, "a"). Это сработало для меня в аналогичном случае.

person isthisthat    schedule 10.01.2019