2012-05-07 2 views
6

Можно ли динамически назначать специальные методы, такие как __getitem__, экземпляру класса с использованием setattr()? Например, если у меня есть это:Настройка специальных методов с помощью setattr()

class Example (object): 
    pass 

А потом попробуйте это:

>>> example = Example() 
>>> setattr(example, '__getitem__', lambda x: 1) 

я получаю это:

>>> example['something'] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'Example' object has no attribute '__getitem__' 

Но, конечно, это прекрасно работает:

>>> example.__getitem__('something') 
1 

Там, очевидно, что-то происходит здесь t Я не понимаю, как Python выполняет поиск методов для такого рода вещей. Должны ли эти методы устанавливаться в классе , а не на экземпляре?

UPDATE:

Итак, я должен сделать это ясно, чем я знаю, что могу увидеть это на Example классе ... Я надеялся, что есть способ, чтобы установить их в-например, но Консенсус, который я вижу до сих пор, заключается в том, что вы не можете этого сделать.

ответ

6

Проблема здесь в том, что __getitem__() определяется на уровне класса, а не на уровне экземпляра:

>>> class Example (object): 
...  pass 
... 
>>> example = Example() 
>>> setattr(Example, '__getitem__', lambda x, y: 1) 
>>> example['something'] 
1 

Если вам это нужно, чтобы быть, специфичная:

>>> class Example(object): 
...  def __getitem__(self, item): 
...   return self._getitem(item) 
... 
>>> example = Example() 
>>> setattr(example, '_getitem', lambda x: 1) 
>>> example['something'] 
1 
>>> example2 = Example() 
>>> setattr(example2, '_getitem', lambda x: 2) 
>>> example['something'] 
1 
>>> example2['something'] 
2 
+0

Хм ... но это повлияло бы на все экземпляры «Пример», а не только на конкретный экземпляр. Вернемся к чертежной доске для меня, я думаю. – larsks

+0

@larsks Это довольно тривиально, чтобы '__getitem __()' вызывать функцию в экземпляре. Я добавлю пример. –

0

ли вам попробуйте monkeypatching класса, а не экземпляр?

>>> example = Example() 
>>> setattr(Example, '__getitem__', lambda self,x: 1)