假设:
f(2,3)
我有一个存在(如无法更改)2位置参数函数,我希望位置参数始终按升序排列;即f(a,b)
,无论我使用哪两个参数(f(c,d)
与示例中的>>> f(*sorted([c,d]))
2 3
相同)
我知道我能做到:
>>> f(*((a,b) if a<b else (b,a)))
2 3
或者我能做到:
,
(Note需要这种形式的元组括号,因为def my_f(a,b):
return f(a,b) if a<b else f(b,a)
的优先级低于三元组......)
或者,
>>> f(*((a,b),(b,a))[a>b])
2 3
所有这些看起来都很蹩脚。我还缺少另一种语法吗?
修改的
我错过了一所旧学校&#39; Python两个成员元组方法。根据True == 1,False == 0方法索引两个成员元组:
>>> f(*{True:(a,b), False:(b,a)}[a<b])
2 3
此外:
numpy.isclose
编辑2
这种愚蠢行为的原因:numpy.isclose有以下用法说明:
对于有限值,isclose使用以下等式来测试是否 两个浮点值是等价的。
绝对(a - b)&lt; =(atol + rtol * absolute(b))
上述等式在a和b中不对称,因此即关闭(a,b) 可能与某些罕见情况下的isclose(b,a)不同。
我希望不会发生。
我正在寻找确保f(*sorted([c,d]))
的参数顺序一致的最快方法。这就是我回避var values = Object.keys(item).map(k => [k, cart, group]);
答案 0 :(得分:6)
实施我的解决方案以防其他人正在寻找。
char LED = 0;
enum {
NONE,
BLINKING,
} state = NONE;
void setup() {
pinMode(BUILTIN_LED, OUTPUT);
Serial.begin(9600); // Opens Serial port
}
void loop() {
if (Serial.available() > 0){
LED = Serial.read();
Serial.print(LED);
switch (LED) {
case '1':
state = NONE;
digitalWrite(BUILTIN_LED, HIGH);
break;
case '2':
state = NONE;
digitalWrite(BUILTIN_LED, LOW);
break;
case '3':
state = BLINKING;
break;
}
}
switch (state) {
case NONE: break;
case BLINKING:
static unsigned long last_blink = 0;
if (millis() - last_blink > 1000)
{
digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED));
last_blink = millis();
}
break;
}
}
此外,@ Tadhg McDonald-Jensen提到您可能无法自行更改功能,因此您可以将功能包装为
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)
答案 1 :(得分:5)
您提到您的用例是np.isclose
。但是,您的方法不是解决真实问题的好方法。但是,鉴于该函数的参数命名不佳,这是可以理解的 - 它有点暗示两个参数都是可互换的。如果它是:numpy.isclose(measured, expected, ...)
(或类似的东西),那就更清楚了。
例如,如果您希望值10
和度量10.51
并允许5%的偏差,那么为了获得有用的结果,必须使用{{ 1}},否则你会得到错误的结果:
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
,NaN
,警告或异常......它绝对避免了问题,但只是通过给出一个不正确的结果(比较并不完美,因为除了它几乎总会得到一个错误的结果; Inf
它很少见。
这是一个有点人为的例子,旨在触发这种行为,而且大多数情况下,如果你使用isclose
或measured, expected
并不重要,但在少数情况下你无法解决它通过交换参数(除非你没有“预期的”结果,但很少发生 - 至少它不应该)。
当expected, measured
被添加到python库时,有一些关于这个主题的讨论:
Symmetry (PEP 485)
[...]
哪种方法最合适取决于提出的问题。如果问题是:“这两个数字是否彼此接近?”,则没有明显的排序,对称测试是最合适的。
但是,如果问题是:“计算值是否在此已知值的x%范围内?”,那么将公差缩放到已知值是合适的,并且非对称测试是最合适的。
[...]
此提案[for
math.isclose
]使用对称测试。
因此,如果您的测试属于第一类并且您喜欢对称测试 - 那么math.isclose
可能是一个可行的替代方案(至少如果您正在处理标量):
math.isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0)
[...]
rel_tol 是相对容差 - 它是 a 和 b 之间允许的最大差值,相对于更大的绝对值 a 或 b 。例如,要设置5%的容差,请传递
math.isclose
。默认容差为rel_tol=0.05
,可确保两个值在大约9个十进制数字内相同。 rel_tol 必须大于零。[...]
如果此答案无法说服您并且您仍想使用1e-09
方法 - 那么您应该按照sorted
olute值(即abs
)进行排序。否则,在比较负数时,您可能会得到令人惊讶的结果:
*sorted([a, b], key=abs)
答案 2 :(得分:2)
对于元组中只有两个元素,第二个元素是首选的习语 - 根据我的经验。它快速,可读等。
不,没有其他语法。还有
(min(a,b), max(a,b))
......但这并不比其他方法特别优越;只是表达它的另一种方式。
在dawg
评论后注意:
具有自定义比较运算符的类可以为min
和max
返回相同的对象。