Асимметричное поведение для классов __getattr__, newstyle vs oldstyle

я пишу здесь впервые, извините, если сообщение не указано или слишком длинное.

Мне было интересно узнать больше о том, как атрибуты объектов выбираются при необходимости. Поэтому я прочитал документацию по 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 __ в классах старого и нового классов при использовании встроенного оператора, такого как +? Может кто-нибудь, пожалуйста, помогите мне понять, что происходит, и в чем была моя ошибка при чтении документации?

Большое спасибо, ваша помощь очень ценится!

8
задан Zaheer Ahmed 23 September 2013 в 05:37
поделиться

3 ответа

См. Поиск специального метода для классов нового стиля .

Специальные методы ищутся непосредственно в объекте класса, объекты экземпляра и, следовательно, __ getattr __ () и __ getattribute __ () игнорируются. Точно по той же причине instance .__ add__ = foobar не работает.

Это сделано для ускорения доступа к атрибутам. Специальные методы вызываются очень часто, и применение к ним стандартного, довольно сложного поиска атрибутов значительно замедлит работу интерпретатора.

Поиск атрибутов для классов старого стиля намного менее сложен (особенно классы старого стиля не поддерживают дескрипторы), поэтому нет причин обрабатывать специальные методы по-разному в классах старого стиля.

5
ответ дан 5 December 2019 в 21:15
поделиться

Ваши функции __ getattr __ ничего не возвращают. Я не знаю, почему класс старого стиля выполняет __ getattr __ перед поиском __ add __ , но это так, и он пытается вызвать возвращаемое значение, которое равно Нет .

Класс нового стиля все делает правильно: вы не определили __ add __ , поэтому он не знает, как их добавить.

2
ответ дан 5 December 2019 в 21:15
поделиться

Дополнительная информация из документации Python:

http://docs.python.org/reference/datamodel.html#customizing-attribute-access

0
ответ дан 5 December 2019 в 21:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: