Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:实现'l[s:e]+;=五`_Python_Range_Operator Overloading - Fatal编程技术网

Python:实现'l[s:e]+;=五`

Python:实现'l[s:e]+;=五`,python,range,operator-overloading,Python,Range,Operator Overloading,我正在实施一个数据结构,以实现快速的附加范围更新: class RAUQ: """ Allow 'l[s:e] += v' update and 'a[i]' query in O(log n) >>> l = RAUQ([0, 10, 20]) ; l [0, 10, 20] >>> l[1] 10 >>> l[2] += 10 ; l [0, 10, 30] >&g

我正在实施一个数据结构,以实现快速的附加范围更新:

class RAUQ:
    """  Allow 'l[s:e] += v' update and 'a[i]' query in O(log n)

    >>> l = RAUQ([0, 10, 20]) ; l
    [0, 10, 20]
    >>> l[1]
    10
    >>> l[2] += 10 ; l
    [0, 10, 30]
    >>> l[0:2] += 3 ; l
    [3, 13, 30]
    >>> l[1:10] -= 4 ; l # Support usual out of bounds slices
    [3, 9, 26]
    """
根据反汇编字节码,
l[i]+=v
表达式被转换为:

l.__setitem__(i, l.__getitem__(i).__iadd__(v))
我觉得这很奇怪(不管怎么说,在原地添加和设置?)


那么,S.O.,用什么样的好方法来实现这一点呢?

以下是我的想法。做这项工作,但感觉不舒服

class RAUQ:

    def __init__(self, iterable):
        # Stripped down example,
        # actual implementation use segment tree.
        self.l = list(iterable)

    def __getitem__(self, i):
        if isinstance(i, slice):
            return _view(self, i)
        return self.l[i]

    def __setitem__(self, i, val):
        if isinstance(i, slice):
            """ No-op: work already done in view"""
            return self
        self.l[i] = val
        return self

    def __str__(self):
        return str(_view(self, slice(None)))

    __repr__ = __str__


class _view:

    def __init__(self, parent, i):
        # generic implementation non designed for single index.
        assert isinstance(i, slice)
        self.l = parent.l
        self.i = i

    def __iter__(self):
        return iter(self.l[self.i])

    def update(self, val):
        """ Add val to all element of the view """
        self.l[self.i] = [x+val for x in self]

    def __iadd__(self, val):
        self.update(val)
        return self

    def __isub__(self, val):
        self.update(-val)
        return self

    def __str__(self):
        return str(list(self))

    __repr__ = __str__

不管有没有黑客,这是唯一的办法;对切片的增广分配首先必须加载切片,然后对结果应用
\uuuu iadd\uuu
。这不能正确支持切片分配;您实现它们的方式只有在以前使用相同的片调用了
\uuu getitem\uuu
时才有效。如果您尝试
r=RAUQ([1]);r[:1]=[5];print(r[0])
您将得到1作为输出,而不是预期的5。如果我发现自己需要做这样的事情,很可能我会与numpy合作,在默认情况下,广播使这成为可能。@rawing:你是对的。我只实现了我需要的部分(RHS是一个标量,而不是任意的可数)。@Martijn:我希望要么是
l.\uu getitem.\uuuuu(I)。\uuu iadd.\uuv
(a la C++:getter返回一个视图/引用),要么是一个带有
\uu add.\uuuu
的版本(表示
l[I]=l[I]+v