Как отменить метод __setattr__? - PullRequest
       9

Как отменить метод __setattr__?

0 голосов
/ 07 февраля 2012

Цель этого вопроса - понять, как «встроены» встроенные функции в python.

Если я переопределю метод setattr, как мне его вернуть? Например, у меня есть класс «Работа», как это:

class WorkingSetAttr:
    def a(self): return 'a'
    def b(self): return 'b'

и класс "NonWorking", как это:

class NonWorkingSetAttr: 
    def a(self): return 'a'
    def b(self): return 'b'
    def __setattr__(self,a,b): pass

Теперь я создаю объекты w и n и запускаю следующее:

w = WorkingSetAttr()
setattr(w,'a',w.b)
print "w.a = %s, w.b = %s" % (w.a(), w.b())

n = NonWorkingSetAttr()
setattr(n, 'a', n.b)
print "n.a = %s, n.b = %s" % (n.a(), n.b())

Вывод:

w.a = b, w.b = b
n.a = a, n.b = b

Обратите внимание, что n.a должно печатать "b", но печатает "a", потому что setattr не меняет атрибут.

Вопрос в том, как мне изменить объект n, чтобы он работал как объект w. Обратите внимание, что я имею в виду объекты, а не классы.

1 Ответ

1 голос
/ 07 февраля 2012

Вы можете просто удалить пользовательский __setattr__ из объекта класса.

>>> n = NonWorkingSetAttr()
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = a, n.b = b
>>> 
>>> del NonWorkingSetAttr.__setattr__
>>>
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = b, n.b = b

Обратите внимание, что это изменяет класс , а не объект.Вы (почти наверняка) не хотите изменять сам объект, потому что тогда у вас есть объект, который выглядит так, как будто это NonWorkingSetAttr, но на самом деле это какая-то динамическая вещь, которую вы на самом деле не понимаете.

Если вы не можете изменить класс, вы можете просто создать подкласс и перезаписать __setattr__ с object 's:

>>> class FixedNonWorkingSetAttr(NonWorkingSetAttr):
...     __setattr__ = object.__setattr__
... 
>>> n = FixedNonWorkingSetAttr()
>>> setattr(n, 'a', n.b)
>>> print("n.a = %s, n.b = %s" % (n.a(), n.b()))
n.a = b, n.b = b
>>> isinstance(n, NonWorkingSetAttr)
True
...