я пишу здесь впервые, извините, если сообщение не указано или слишком длинное.
Мне было интересно узнать больше о том, как атрибуты объектов выбираются при необходимости. Поэтому я прочитал документацию по Python 2.7 под названием «Модель данных» здесь , я встретил __ getattr __
и, чтобы проверить, понял ли я его поведение, я написал эти простые (и неполные) обертки строк.
class OldStr:
def __init__(self,val):
self.field=val
def __getattr__(self,name):
print "method __getattr__, attribute requested "+name
class NewStr(object):
def __init__(self,val):
self.field=val
def __getattr__(self,name):
print "method __getattr__, attribute requested "+name
Как вы можете видеть, они одинаковы, за исключением того, что они являются классами старого стиля против классов нового стиля. Поскольку в цитируемом тексте написано __ getattr __
«Вызывается, когда поиск атрибута не нашел атрибут в обычных местах», я хотел попробовать операцию + на двух экземплярах этих классов, чтобы посмотреть, что произошло, ожидая идентичное поведение.
Но результаты, которые я получил, меня немного озадачили:
>>> x=OldStr("test")
>>> x+x
method __getattr__, attribute requested __coerce__
Traceback (most recent call last):
File "", line 1, in
TypeError: 'NoneType' object is not callable
Хорошо! Я не определил метод для __ coerce __
(хотя я ожидал запрос на __ add __
, nevermind :), поэтому __ getattr __
вмешался и возвратил бесполезную вещь. Но тогда
>>> y=NewStr("test")
>>> y+y
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for +: 'NewStr' and 'NewStr'
Почему это асимметричное поведение между __ getattr __
в классах старого и нового классов при использовании встроенного оператора, такого как +? Может кто-нибудь, пожалуйста, помогите мне понять, что происходит, и в чем была моя ошибка при чтении документации?
Большое спасибо, ваша помощь очень ценится!
См. Поиск специального метода для классов нового стиля .
Специальные методы ищутся непосредственно в объекте класса, объекты экземпляра и, следовательно, __ getattr __ ()
и __ getattribute __ ()
игнорируются. Точно по той же причине instance .__ add__ = foobar
не работает.
Это сделано для ускорения доступа к атрибутам. Специальные методы вызываются очень часто, и применение к ним стандартного, довольно сложного поиска атрибутов значительно замедлит работу интерпретатора.
Поиск атрибутов для классов старого стиля намного менее сложен (особенно классы старого стиля не поддерживают дескрипторы), поэтому нет причин обрабатывать специальные методы по-разному в классах старого стиля.
Ваши функции __ getattr __
ничего не возвращают. Я не знаю, почему класс старого стиля выполняет __ getattr __
перед поиском __ add __
, но это так, и он пытается вызвать возвращаемое значение, которое равно Нет
.
Класс нового стиля все делает правильно: вы не определили __ add __
, поэтому он не знает, как их добавить.
Дополнительная информация из документации Python:
http://docs.python.org/reference/datamodel.html#customizing-attribute-access