鉴于:
>>> a,b=2,3
>>> c,d=3,2
>>> def f(x,y): print(x,y)
Run Code Online (Sandbox Code Playgroud)
我有一个存在(如无法改变)2位置参数函数,我希望位置参数始终按升序排列; 即,f(2,3)无论我使用哪两个参数(与示例中f(a,b)的相同f(c,d))
我知道我能做到:
>>> f(*sorted([c,d]))
2 3
Run Code Online (Sandbox Code Playgroud)
或者我可以这样做:
>>> f(*((a,b) if a<b else (b,a)))
2 3
Run Code Online (Sandbox Code Playgroud)
(注意这种形式需要元组括号,因为,它的优先级低于三元组...)
要么,
def my_f(a,b):
return f(a,b) if a<b else f(b,a)
Run Code Online (Sandbox Code Playgroud)
所有这些看起来都有些笨拙.我还缺少另一种语法吗?
编辑
我错过了'老派'Python的两个成员元组方法.根据True == 1,False == 0方法索引两个成员元组:
>>> f(*((a,b),(b,a))[a>b])
2 3
Run Code Online (Sandbox Code Playgroud)
也:
>>> f(*{True:(a,b), False:(b,a)}[a<b])
2 3
Run Code Online (Sandbox Code Playgroud)
编辑2
这个愚蠢的练习的原因:numpy.isclose有以下用法说明:
对于有限值,isclose使用以下等式来测试两个浮点值是否相等.
绝对值(a - b)<=(atol + rtol*absolute(b))
上述等式在a和b中不对称,因此在某些罕见的情况下,isclose(a,b)可能与isclose(b,a)不同.
我宁愿没有发生.
我正在寻找最快的方法来确保参数的numpy.isclose顺序是一致的.这就是我回避的原因f(*sorted([c,d]))
实施我的解决方案以防其他人正在寻找.
def sort(f):
def wrapper(*args):
return f(*sorted(args))
return wrapper
@sort
def f(x, y):
print(x, y)
f(3, 2)
>>> (2, 3)
Run Code Online (Sandbox Code Playgroud)
此外,@ Tadhg McDonald-Jensen提到您可能无法自行更改功能,因此可以将功能包装为
my_func = sort(f)
Run Code Online (Sandbox Code Playgroud)
你提到你的用例是np.isclose.但是,您的方法不是解决实际问题的好方法.但是,鉴于该函数的参数命名不佳,这是可以理解的 - 它有点暗示两个参数都是可互换的.如果它是:( numpy.isclose(measured, expected, ...)或类似的东西)它会更清楚.
例如,如果您期望值10和度量10.51并允许5%偏差,那么为了获得有用的结果,您必须使用np.isclose(10.51, 10, ...),否则您将得到错误的结果:
>>> import numpy as np
>>> measured = 10.51
>>> expected = 10
>>> err_rel = 0.05
>>> err_abs = 0.0
>>> np.isclose(measured, expected, err_rel, err_abs)
False
>>> np.isclose(expected, measured, err_rel, err_abs)
True
Run Code Online (Sandbox Code Playgroud)
很明显地看到,第一个给出正确的结果,因为实测值是不是在公差范围内预期值.那是因为相对不确定性是预期值的"属性",而不是您与之比较的值!
因此,通过"排序"参数来解决这个问题是错误的.这是一个有点像,因为分母包含零除以零能给改分裂分子和分母NaN,Inf中,警告或异常......其definetly避免了这个问题,但只是通过提供不正确的结果(比较不完美,因为除了它几乎总会给出错误的结果; isclose它很少见.
这是一个有点人为的例子,旨在触发这种行为,大多数情况下,如果你使用measured, expected或者expected, measured在少数情况下它并不重要,你无法通过交换参数解决它(除非你没有"预期" "结果,但很少发生 - 至少它不应该发生."
在math.isclose添加到python库时,有一些关于这个主题的讨论:
对称性(PEP 485)
[...]
哪种方法最合适取决于提出的问题.如果问题是:"这两个数字是否彼此接近?",则没有明显的排序,对称测试最合适.
但是,如果问题是:"计算值是否在此已知值的x%范围内?",则将公差缩放到已知值是合适的,并且非对称测试是最合适的.
[...]
该提议[用于
math.isclose]使用对称测试.
因此,如果您的测试属于第一类并且您喜欢对称测试 - 那么math.isclose可能是一个可行的替代方案(至少如果您正在处理标量):
math.isclose(a,b,*,rel_tol = 1e-09,abs_tol = 0.0)
[...]
rel_tol是相对容差 - 它是a和b之间允许的最大差值,相对于a或b的较大绝对值.例如,要设置5%的容差,请通过
rel_tol=0.05.默认容差为1e-09,确保两个值在大约9个十进制数字内相同.rel_tol必须大于零.[...]
如果这个答案不能说服你,你仍然想要使用一种sorted方法 - 那么你应该按照abs你的价值观(即*sorted([a, b], key=abs)).否则,在比较负数时,您可能会得到令人惊讶的结果:
>>> np.isclose(-10.51, -10, err_rel, err_abs) # -10.51 is smaller than -10!
False
>>> np.isclose(-10, -10.51, err_rel, err_abs)
True
Run Code Online (Sandbox Code Playgroud)
根据我的经验,对于元组中只有两个元素的情况,第二个是首选习惯用法。它具有快速、可读等优点。
不,实际上没有其他语法。还有
(min(a,b), max(a,b))
Run Code Online (Sandbox Code Playgroud)
...但这并不是特别优于其他方法;只是另一种表达方式。
评论后请注意dawg:
具有自定义比较运算符的类可以为min和返回相同的对象max。