我使用Python来包装一个强大的库(来自另一种语言)来操纵表达式和关系。就此而言,我广泛使用运算符的重载,它就像一个魅力。
现在,我需要定义一个max
函数,该函数将应用于我的表达式,以生成一个直观表示“迭代中所有表达式的最大值的新表达式(这些表达式尚未评估)。”< / p>
由于内置函数max
使用迭代器和某种实现为__leq__
等的顺序关系,(我用它来生成两个表达式的关系)我最终得到了废话我将内置max
应用于一组表达式。
更具体地说,
>>> max(e1, e2, e3)
e3
虽然我很想提出某种例外情况说“请使用我的特定功能,我指的是这会产生你合理期望的新表达”
我的底线是,即使我有一个不同的功能实现表达式max
:
max(e1, e2, e3)
。max
像往常一样使用普通的Python对象。我能想到的唯一解决方法是从key
选项max
开始,当它遇到特定类型的对象时引发异常:
def newkey(p):
if isinstance(p, Expression):
raise SyntaxError("Use function `foo` for computing `max`")
# fallback to regular behaviour I know nothing about yet
max(e1, e2, e3, key=newkey)
现在,我无法强制用户在每次调用key
时指定max
选项。事实上,如果可以,我会告诉他们使用不同的max
功能......
你能看出一条出路吗? (或更好的解决方法)
答案 0 :(得分:2)
由于内置函数max使用迭代器和某种实现为
__leq__
等的顺序关系(我用它来生成两个表达式的关系)
丰富的比较方法返回的类型需要在Python 3中实现__nonzero__
或__bool__
,以定义当您尝试将其解释为布尔值时会发生什么。 __nonzero__
应该做什么有两种合理的可能性。
如果实际评估基础表达式并执行比较是合理的,您可以设计__nonzero__
方法来做到这一点。如果您正在构建某种惰性操作库,这将是有意义的。在这种情况下,max
只会起作用,但它会隐含地强制评估其论点。这可能不太可取。
或者,您可能会__nonzero__
引发TypeError。在这种情况下,当max
试图决定两个表达式中哪一个更大时,它会引发一个TypeError。
答案 1 :(得分:0)
您可以使用装饰器覆盖max它将提供相同的行为但在需要时引发异常检查以下代码
def dec(ff):
def _f(*args):
for p in args:
if isinstance(p, Expression):
raise SyntaxError("Use function `foo` for computing `max`")
else:
return ff(*args)
return _f
max = dec(max)