python: как получить доступ к атрибутам функций

Я пытаюсь получить доступ к атрибутам функций-членов, но не могу понять, почему я могу получить доступ только через файл __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, если пытаюсь получить доступ «напрямую»?


person jimifiki    schedule 29.07.2012    source источник
comment
Вы пытаетесь добавить атрибуты метода в определение класса?   -  person jdi    schedule 30.07.2012
comment
Почему именно вы этого хотите?   -  person Wooble    schedule 30.07.2012
comment
Я хочу этого, потому что это функция Python. В начале я делал нечто подобное, когда хотел, чтобы производные классы устанавливали атрибут одного из своих методов. Мне нужны правильные указатели на ответ.   -  person jimifiki    schedule 30.07.2012
comment
Да, я пытаюсь добавить атрибуты. Но что меня больше волнует, так это понять, как работает язык. Я знаю, что это может легко стать плохой практикой.   -  person jimifiki    schedule 30.07.2012
comment
Причина: stackoverflow. com/questions/7891277/   -  person jdi    schedule 30.07.2012


Ответы (2)


Из-за того, как реализованы объекты instancemethod. Они используют нестандартный метод получения атрибутов, который не разрешает доступ к нестандартным атрибутам.

person Amber    schedule 29.07.2012
comment
Вот такой ответ я хотел. Можете ли вы сказать мне, где я могу прочитать больше? Я также хотел бы знать, что такое нестандартные атрибуты. Никто не говорил мне об этом понятии!! - person jimifiki; 30.07.2012
comment
Прочтите здесь stackoverflow. com/questions/7891277/ - person jdi; 30.07.2012
comment
Эта ссылка предполагает, что это не определенное количество атрибутов. А скорее невозможность сделать это на связанных или несвязанных методах. - person jdi; 30.07.2012
comment
instancemethod — это класс, реализованный на C как часть реализации CPython. Таким образом, он не обладает встроенной гибкостью, которой обладают обычные объекты Python. У него есть __dict__ (потому что реализация C предоставляет его), но его __getattribute__ не сопоставляется автоматически с вещами в этом словаре. - person Amber; 30.07.2012

Не знаю, зачем ты вообще это сделал, но...

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 - использование и злоупотребление

person allyourcode    schedule 27.11.2012