这是一个有效的解决方案。它不完整并且充满了非常糟糕的设计选择,但我希望它有所帮助。
class Expr(object):
def __init__(self, op, left, right):
self.op = op
self.left = left
self.right = right
def __call__(self, current):
l = self._replace_current(self.left, current)
r = self._replace_current(self.right, current)
return self._do_operation(l, r)
def _replace_current(self, val, current):
if val == 'current':
return current
elif isinstance(val, Expr): # recurse
return val(current)
else:
return val
def _do_operation(self, l, r):
if self.op == '+':
return l + r
elif self.op == '*':
return l * r
elif self.op == '-':
return l - r
def __add__(self, other):
return self._left_op('+', other)
def __radd__(self, other):
return self._right_op('+', other)
def __mul__(self, other):
return self._left_op('*', other)
def __rmul__(self, other):
return self._right_op('*', other)
def __sub__(self, other):
return self._left_op('-', other)
def __rsub__(self, other):
return self._right_op('-', other)
def _left_op(self, op, other):
if isinstance(other, Current):
return Expr(op=op, left=self, right='current')
else:
return Expr(op=op, left=self, right=other)
def _right_op(self, op, other):
if isinstance(other, Current):
return Expr(op=op, left='current', right=self)
else:
return Expr(op=op, left=other, right=self)
class Current(Expr):
def __init__(self):
super(Current, self).__init__(None, None, None)
def __call__(self, current):
return current
def _left_op(self, op, other):
return Expr(op=op, left='current', right=other)
def _right_op(self, op, other):
return Expr(op=op, left=other, right='current')
current = Current()
class YourObj(object):
def __init__(self, a, b):
self.a = a
self.b = b
def __call__(self, **kw):
for key, val in kw.iteritems():
# You should probably make sure it is actually an attribute of YourObj
if isinstance(val, Expr):
current = self.a
new_val = val(current)
setattr(self, key, new_val)
else:
setattr(self, key, val)
您可以执行以下操作:
obj = YourObj(a=4, b=5)
obj(a=current - 4 + current * current)
这基本上是嵌入在 python 数学运算中的表达式解释器。
每当您对(如 +)使用操作时current
,它将返回一个Expr
(因为它覆盖__add__
and __radd__
),它将注册这是哪个操作,以及它的每个操作数是什么。这些表达式可以嵌套,所以如果你说current + 4 - current
,它将返回Expr(op='-', left=Expr(op='+', left='current', right=4), right='current')
。
然后可以通过像函数一样调用表达式并将应该替换“当前”的值传递给它来评估表达式。当您评估一个表达式时,它将:
- 用传递的值替换所有出现的“当前”
- 递归地评估嵌套函数
- 返回整个表达式的最终结果
当您这样做时obj(a=current + 4)
,将调用的__call__
方法。YourObj
它将评估结果的表达式current + 4
并将其存储在a
.
我希望这更清楚。也许我应该重命名一些“当前”以减少混乱。