Python运算符重载和运算符关联性
我正在编写一个python程序,其中需要重载>>操作符。我面临的问题是,这个操作符必须是右关联的。因此,如果我做以下几点Python运算符重载和运算符关联性,python,operator-overloading,Python,Operator Overloading,我正在编写一个python程序,其中需要重载>>操作符。我面临的问题是,这个操作符必须是右关联的。因此,如果我做以下几点 A >> B >> C >> D >> E 我想把它解析为 (A >> (B >> (C >> (D >> E)))) 据我所知,在python中,这个操作符是左联想的,所以我会得到 ((((A >> B) >> C) >> D) >&
A >> B >> C >> D >> E
我想把它解析为
(A >> (B >> (C >> (D >> E))))
据我所知,在python中,这个操作符是左联想的,所以我会得到
((((A >> B) >> C) >> D) >> E)
在执行运算符重载时,python中是否仍有更改运算符默认关联性的方法?这不是运算符的问题。Python从左到右求值:
因此,在这种情况下需要括号,因为它都是相同的运算符 这是可以做到的……但这需要一些努力。其基本思想是使用right shift操作符创建和更新一种新类型的对象,以延迟实际计算 例如,假设上面的变量:A、B、C、D和E都是类型为Actual的对象。我们将引入一个新的延迟类,该类是由对实际实例的rshift操作生成的。Deferred还实现rshift操作符,它更新对象并返回自身 (顺便说一句,对于这个答案的其余部分,我假设A、B、C、D和E是不可变的,并且rshift操作生成一个新对象。) 将被计算为
F = Deferred(A,B) >> C >> D >> E
F = Deferred(A,B,C) >> D >> E
F = Deferred(A,B,C,D) >> E
F = Deferred(A,B,C,D,E)
F维护一个缓存的Actual实例,该实例是按照相反的顺序计算的。此外,F实现了与Actual相同的接口,因此在Deferred实例上调用的方法被委托给Actual的缓存实例
我不知道你在做什么样的计算,所以在下面的例子中,我编造了一些琐碎的东西,只是为了证明当延迟计算实际执行时,它们是反向的
class Var(object):
def __init__(self):
pass
@property
def name(self):
return self._name( )
@property
def length(self):
return len(self.name)
class Actual(Var):
def __init__(self, name):
Var.__init__(self)
self._text = name
def _name(self):
return self._text
def __rshift__(self, other):
if isinstance(other, Actual):
return Deferred(self, other)
return len(self.name)
@staticmethod
def NewFromShiftComputation(sequence):
x = ' >> '.join(reversed(map(lambda actual: actual.name, sequence)))
return Actual(x)
class Deferred(Var):
def __init__(self, *args):
Var.__init__(self)
self._items = [ ]
self._actual = None #-- cached "actual"
for item in args:
self._items.append(item)
def _name(self):
self._assure_actual( )
return self._actual.name
def __rshift__(self, other):
self._actual = None #-- Invalidate the cached "actual"
self._items.append(other)
return self
def _assure_actual(self):
if self._actual is None:
self._actual = Actual.NewFromShiftComputation(self._items)
A = Actual('A')
B = Actual('B')
C = Actual('C')
D = Actual('D')
E = Actual('E')
F = A >> B >> C >> D >> E
print F.name
print F.length
我可能错了,但这不是运算符重载的问题,而是标准的“操作顺序”问题吗?如果它们都是同一个操作符,那么它将从左到右重载@wim,我想到了,哈哈。只是习惯于从左到右阅读的人用另一种方式阅读要自然得多。我还考虑过重载=操作符,因为我认为这是正确的关联,但那会非常难看。这个用例是什么?重载标准操作符来完成神奇的事情几乎总是一个坏主意,因为这会让其他人(或者你在六个月内)很难理解和维护代码。考虑<代码> DEF FUNC(*ARGs):…和<代码> FUNC(A,B,C,D,E)。虽然你可能还是通过一个吻,一个名字很好的功能更好。Python并不适合在Python本身中创建自定义DSL,因为语法很难扩展。我相信你们可以玩,但它很乱,我很害怕。我只是希望有一种方法可以让python解释器在某些情况下改变运算符的关联性。@martega:是的,如果可以更改interp的规则,这可能会破坏您正在使用的其他lib。为什么不创建一个函数,将它们作为参数,并按照正确的操作顺序运行呢?
class Var(object):
def __init__(self):
pass
@property
def name(self):
return self._name( )
@property
def length(self):
return len(self.name)
class Actual(Var):
def __init__(self, name):
Var.__init__(self)
self._text = name
def _name(self):
return self._text
def __rshift__(self, other):
if isinstance(other, Actual):
return Deferred(self, other)
return len(self.name)
@staticmethod
def NewFromShiftComputation(sequence):
x = ' >> '.join(reversed(map(lambda actual: actual.name, sequence)))
return Actual(x)
class Deferred(Var):
def __init__(self, *args):
Var.__init__(self)
self._items = [ ]
self._actual = None #-- cached "actual"
for item in args:
self._items.append(item)
def _name(self):
self._assure_actual( )
return self._actual.name
def __rshift__(self, other):
self._actual = None #-- Invalidate the cached "actual"
self._items.append(other)
return self
def _assure_actual(self):
if self._actual is None:
self._actual = Actual.NewFromShiftComputation(self._items)
A = Actual('A')
B = Actual('B')
C = Actual('C')
D = Actual('D')
E = Actual('E')
F = A >> B >> C >> D >> E
print F.name
print F.length