2012-02-07 1 views
0

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

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

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

и класс «нерабочим», как это:

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

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

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 не изменяет атрибут.

Вопрос: Как я должен изменить объект п так, что он работает как объект ш. Заметьте, что я имею в виду объекты, а не классы.

+0

Это (почти) всегда плохая идея, чтобы изменить _objects_ без изменения их классы , В конце концов, экземпляр предназначен для экземпляра определенного класса! Если вы нарушаете эти отношения, вы получаете «вещи», о которых вы мало что знаете, и которые вы не можете отлаживать. – katrielalex

+0

@KevinDTimm встроенный метод Python 'setattr' устанавливает атрибут, который в свою очередь вызывает' __setattr__' объекта класса. – katrielalex

+0

'__setattr__' вызывается из setattr. Посмотрите, как это работает для случая «w» (вывод изменяется с «a» на «b»). Дело в том, что: как я могу вернуть встроенную функцию, если я просто «сломал» ее. – Juha

ответ

1

Вы можете просто удалить пользовательский объект __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-х:

>>> 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 
+0

Исправьте, если я ошибаюсь, но object = instance of класс? А в python объекты динамические? Я имею в виду, что это все еще экземпляр класса, даже если у него есть дополнительные вещи, верно? – Juha

+1

Да: вы _could_ настраиваете объект. Вы даже можете сделать некоторые действительно волосатые вещи, например, модифицировать класс экземпляра на лету. Но вы не должны, если вам это абсолютно не нужно, потому что вы получите объекты, которые выглядят как _, они являются экземплярами некоторого класса, но на самом деле не имеют одинаковых методов. Это приведет к отладке ада. – katrielalex

+0

Подумайте об этом: если у вас есть код, определяющий класс, и создайте экземпляр этого класса, вы ожидаете, что результирующий объект - независимо от того, сколько вычислений вы сделали с ним - будет действовать как экземпляр этого класса. – katrielalex