Redirecionando definições de função em python
-
22-08-2019 - |
Pergunta
Este é um exemplo muito artificial, uma vez que não é fácil de explicar o contexto em que eu acabei implementação desta solução. No entanto, se alguém pode responder por essa peculiaridade especial acontece, eu ficaria grato.
O exemplo:
class A(dict):
def __init__(self):
self['a'] = 'success'
def __getitem__(self, name):
print 'getitem'
return dict.__getitem__(name)
class B(object):
def __init__(self):
self._a = A()
setattr(self, '__getitem__', self._a.__getitem__)
b = B()
c = b['a']
Esta saídas:
c = b['a']
TypeError: 'B' object is unsubscriptable
Mesmo que seja uma forma bizarra de fazer isso (claramente subclasse seria mais lógico), por que não encontrar o método que eu definir explicitamente?
Se eu fizer isso:
dir(b)
fico com esta:
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_a']
O mesmo problema ocorre com outros métodos, como __iter__
. O que é sobre explicitamente definir este método que funciona?
Solução
Quando você usa colchetes []
aparência python na classe. Você deve definir o método na classe.
Aqui está seu código adaptado:
class A(dict):
def __init__(self):
self['a'] = 'success'
def __getitem__(self, name):
print 'getitem!'
return dict.__getitem__(self, name)
class B(object):
def __init__(self):
self._a = A()
B.__getitem__ = self._a.__getitem__
b = B()
c = b['a']
Outras dicas
Isso é porque você não pode substituir métodos de classe especial na mosca.
Eu não era capaz de encontrar uma referência sobre isso, mas é basicamente porque são métodos de classe e não estão autorizados a ser métodos de instância.