`self[key] += value` 的魔法方法是什么?

4

Python中有一个神奇的方法__setitem__,用于对序列类型进行赋值操作=。在容器级别上,是否有增强赋值操作+=的魔术方法呢?这个操作似乎可以优雅地降级为项类型的增强赋值操作。这是合理的。但几乎所有其他操作都有一个魔术方法,我认为在序列类型中应该有一组这些运算符的方法。我错过了吗?

应用程序是一种数据库。考虑使用SELECT实现__getitem__,使用INSERT实现__setitem__。应该有类似__additem__等用于UPDATE的方法,对吧?

from __future__ import print_function
class Item(object):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return "Item " + str(self.value)
    def __iadd__(self, other):
        print("Item iadd", self, other)
        return Item(self.value + "+" + other.value)

class Container(object):
    def __getitem__(self, key):
        print("Container getitem", key)
        return Item(key)
    def __setitem__(self, key, value):
        print("Container setitem", key, value)
        return self
    def __additem__(self, key, value):
        print("Container additem would be nice", key, value)
        return self

这是 SELECT 语句:

>>> c = Container()
>>> _ = c['key']
Container getitem key

这里是INSERT语句:

>>> c['key'] = Item('other')
Container setitem key Item other

如何实现UPDATE?而不是将其分解为SELECT和INSERT:

>>> c['key'] += Item('other')
Container getitem key
Item iadd Item key Item other
Container setitem key Item key+other

有没有一种实现增强赋值的方法不需要将所有行为都放在Item类中,而不是分解步骤?

您可以将上述代码复制并粘贴到Python解释器中,或者在此Python fiddle上尝试: http://pythonfiddle.com/add-item-for-sequence/


相关问题展示了self[key] += value的反编译过程。

1个回答

3
没有什么魔法的__additem__方法。 c[k] += v会被转换为魔术方法调用:c.__setitem__(c.__getitem__(k).__iadd__(v))
包括__setitem__调用是因为并非所有Python对象都支持原地加法。不可变对象(如intfloat)不支持,因此将调用__add__而不是__iadd__(__add__必须返回一个新值)。
我认为使数据库按照您想要的方式工作的唯一方法是编写__getitem__以便它返回一个特殊的“项代理”类型。代理最初不会有任何行为,但是当在其上查找属性或方法时(或者调用__magic__方法),它将执行必要的数据库操作以使其工作。对于大多数方法和属性查找,它需要查询数据库以获取实际数据,然后返回适当的方法或值。如果调用了已知的就地修改方法(如append__iadd__),则它可以执行不同的数据库操作(如UPDATE而不是SELECT)。
编写这样的代理类型并不是很容易,但也不是非常困难。如果要处理许多类型的对象,则需要考虑许多特殊情况。根据数据库可以保存的类型集有多窄,可能可以将需要代理复制的方法和属性列表缩小到只有几个(例如算术和比较运算符,以及__int____float__,如果仅需要支持数值类型)。
另一方面,您可能会发现,当您可以使用更少的代码执行SELECTINSERT时,这并不值得开发。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接