英文:
How to wrap __getitem__ method correctly to keep square brackets functionality
问题
我有一个类B,它包装了类A的`__getitem__`方法:
def my_decorator(method):
def wrapper(*args, **kwargs):
print('Decorator')
method(*args, **kwargs)
return wrapper
class A:
def __getitem__(self, idx):
print(idx)
class B:
def __init__(self):
self._a = A()
self._a.__getitem__ = my_decorator(self._a.__getitem__)
def get_a(self, idx):
self._a[idx]
b = B()
b.get_a(0)
我期望的输出应该是:
Decorator
0
但是实际上我得到的输出是:
0
如果我将`get_a`方法改为如下所示,我可以得到期望的行为:
def get_a(self, idx):
self._a.__getitem__(idx)
似乎包装`__getitem__`方法并不影响使用方括号的访问方式。有没有办法使原始代码在使用方括号访问时也能正常工作?我不想修改`get_a`的实现方式。
英文:
I have a class B that wraps the the __getitem__
method of class A:
def my_decorator(method):
def wrapper(*args, **kwargs):
print('Decorator')
method(*args, **kwargs)
return wrapper
class A:
def __getitem__(self, idx):
print(idx)
class B:
def __init__(self):
self._a = A()
self._a.__getitem__ = my_decorator(self._a.__getitem__)
def get_a(self, idx):
self._a[idx]
b = B()
b.get_a(0)
I would expect the following output:
Decorator
0
But instead I just get:
0
If I change get_a
method as follows, I get the expected behaviour:
def get_a(self, idx):
self._a.__getitem__(idx)
It seems that wrapping the __getitem__
method doesn't affect the access with square brackets. Is there any way to make the original code work with square brackets access? I don't want to modify the implementation of get_a
.
答案1
得分: 4
self._a[idx]
相当于 type(self._a).__getitem__(idx)
,而不是 self._a.__getitem__(idx)
。你定义的实例属性 __getitem__
在 []
语法中会被忽略。
你需要定义一个继承自 A
的子类,重写 __getitem__
方法。
class A:
def __getitem__(self, idx):
print(idx)
class SubA(A):
def __getitem__(self, idx):
print('Decorator')
return super().__getitem__(idx)
class B:
def __init__(self):
self._a = SubA()
def get_a(self, idx):
self._a[idx]
b = B()
b.get_a(0)
(请注意:__getitem__
应该真正返回一个值,这样的话 get_a
需要显式地返回 self._a[idx]
的值。)
英文:
self._a[idx]
is equivalent to type(self._a).__getitem__(idx)
, not self._a.__getitem__(idx)
. The instance attribute __getitem__
you define is ignored by the []
syntax.
You need to define a subclass of A
that overrides __getitem__
.
class A:
def __getitem__(self, idx):
print(idx)
class SubA(A):
def __getitem__(self, idx):
print('"Decorator"')
return super().__getitem__(idx)
class B:
def __init__(self):
self._a = SubA()
def get_a(self, idx):
self._a[idx]
b = B()
b.get_a(0)
(Just to note: __getitem__
should really return a value, in which case get_a
needs to explicitly return the value of self._a[idx]
.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论