Python: setattr для классов старого стиля?


Как я могу выполнить эквивалент _ _ setattr__ для класса старого стиля?

2 3

2 ответа:

Если вы хотите установить атрибут для экземпляра класса old style, вы можете использовать setattr встроенная функция, она должна работать и для классов старого стиля . Пример -

>>> class Foo:
...     def __init__(self,blah):
...             self.blah=blah
... 
>>> foo = Foo("Something")
>>> foo.blah
'Something'
>>> setattr(foo,'blah','somethingElse')
>>> foo.blah
'somethingElse'

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

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

Tl; dr

Используйте self.__dict__[attr_name] = attr_value в методе __setattr__(self, attr_name, attr_value) класса старого стиля.

__setattr__() встречается с классом старого стиля

Интересно, что и Python 2.7 и 3 делают вызов __setattr__() методов, определенных классами старого стиля. Однако, в отличие от классов нового стиля, классы старого стиля не предоставляют значения по умолчанию Метод __setattr__(). Ни для кого не удивительно, что это ужасно усложняет методы __setattr__() в классах старого стиля.

В подклассе __setattr__() класса нового стиля суперкласс __setattr__() обычно вызывается в конце, чтобы задать требуемый атрибут. В подклассе __setattr__() класса старого стиля это обычно вызывает исключение; в большинстве случаевне существует суперкласса __setattr__(). Вместо этого требуемая пара ключ-значение специальной переменной экземпляра __dict__ должна быть установлена вручную.

Пример или это Не случилось

Рассмотрим большой класс старого стиля, напоминающий фразу "черный козел леса с тысячью молодых" и определяющий __setattr__(), чтобы префиксировать имя передаваемого атрибута la_:

class ShubNiggurath:
    def __setattr__(self, attr_name, attr_value):
        # Do not ask why. It is not of human purport.
        attr_name = 'la_' + attr_name

        # Make it so. Do not call
        # super(ShubNiggurath, self).__setattr__(attr_name, attr_value), for no
        # such method exists.
        self.__dict__[attr_name] = attr_value

Асимметрия в темноте

Любопытно, что классы старого стиля действительно предоставляют метод по умолчанию __getattr__(). Как питон 2.7 допустил эту непристойную асимметрию, не стоит и думать - ибо она одинаково отвратительна и постыдна!

Но это является.