元组和三元和位置参数

时间:2017-05-19 20:51:41

标签: python python-3.x

假设:

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]);

的原因

3 个答案:

答案 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它很少见。

这是一个有点人为的例子,旨在触发这种行为,而且大多数情况下,如果你使用isclosemeasured, 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 评论后注意:

具有自定义比较运算符的类可以为minmax返回相同的对象。