我正在编写一个与Jython一起使用的Java集合类。我希望最终用户能够以这种方式操作集合:
myCollection = MyJavaCollection()
myCollection[0] += 10.;
a = myCollection[0]; //a = 10
myCollection[0] += 20.;
b = myCollection[0]; //b = 20
我在Python文档中找到的是以下方法:
__getitem__
和__setitem__
方法应该为括号运算符重载做好工作。
__iadd__
方法是+=
的理想候选人。
我怎样才能将两者混合在一起?
答案 0 :(得分:6)
请注意myCollection[0] += 10.;
实际上会被解释为:
myCollection.__setitem__(0, myCollection.__getitem__(0).__iadd__(10.))
因此,要完成这项工作,您需要实施:
__getitem__
上__setitem__
和MyJavaCollection
;和__iadd__
(或__add__
,如果__iadd__
没有实现,Python会回归到 将要返回的任何.__getitem__
,而不是MyJavaCollection
本身 - 如果它会返回已经实现添加的内容,例如示例中的float
,那就没事了。快速演示:
>>> class Container(object):
def __init__(self, contained):
self.contained = contained
def __getitem__(self, key):
print "Container.__getitem__"
return self.contained
def __setitem__(self, key, val):
print "Container.__setitem__"
self.contained = val
>>> class Contained(object):
def __add__(self, other):
print "Contained.__add__"
return "foo"
>>> test = Container(Contained())
>>> test[0] += 1
Container.__getitem__
Contained.__add__
Container.__setitem__
>>> test.contained
'foo'
答案 1 :(得分:2)
你原来的问题有一个列表作为索引传递,所以我写这个假设你想要访问2D列表的(i, j)
元素。你可以通过以下方式定义你的类来做到这一点:
class MyJavaCollection:
def __init__(self, values):
self.values = values
def __getitem__(self, indices):
"""
Returns the item at index (i, j) given an index list [i, j].
"""
return self.values[indices[0]][indices[1]]
def __setitem__(self, indices, value):
"""
Sets the (i, j)th item to the input value given an input
index list [i, j].
"""
self.values[indices[0]][indices[1]] = value
当您传递索引列表{{1>时,您正在重载__getitem__
和__setitem__
方法以检索或设置(i, j)
列表中的values
元素}}。如果您的值只是数字,则语法[i, j]
会将myCollection([1, 1]) += 10
添加到10
。
如另一个答案中所述,如果您不是简单地在对象中存储数字,那么您可能需要覆盖数据所包含的任何类的values[1][1]
或__add__
方法,以获得你想要的。
测试我的示例类:
__iadd__
documentation on special method names为您提供了有关此类特殊方法的所有信息。如果您不确定可能需要超载的方法,它可以是一个搜索的好地方。