Перенаправление определений функций в python
-
22-08-2019 - |
Вопрос
Это очень надуманный пример, поскольку нелегко объяснить контекст, в котором я в конечном итоге реализовал это решение.Однако, если кто-нибудь может ответить, почему происходит именно эта особенность, я был бы благодарен.
Пример:
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']
Это выводит:
c = b['a']
TypeError: 'B' object is unsubscriptable
Несмотря на то, что это странный способ сделать это (очевидно, что разделение на подклассы было бы более логичным), почему он не находит метод, который я явно установил?
Если я сделаю это:
dir(b)
Я понимаю это:
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_a']
Та же проблема возникает и с другими методами, такими как __iter__
.Что такого в явном определении этого метода, который работает?
Решение
Когда вы используете скобки []
python заглядывает в класс.Вы должны установить метод в классе.
Вот адаптированный вами код:
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']
Другие советы
Это происходит потому, что вы не можете переопределить специальные методы класса "на лету".
Я не смог найти ссылку на это, но в основном потому, что они являются методами класса и им не разрешено быть методами экземпляра.