列表中三元运算符的折叠

时间:2018-12-29 21:38:44

标签: python python-3.x

以下代码可用(demo

f=lambda m, x:m and(x&1 and m.pop(0)or m.pop(0)[::-1])+f(m, x+1)
print(f([[4, 3, 2, 1], [5, 6, 7, 8], [12, 11, 10, 9], [13, 14, 15, 16]],0))

# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

这里有逻辑:

m.pop(0) if x&1 else m.pop(0)[::-1]

请解释为什么折叠到以下视图时代码无法正确执行?

[m.pop(0)[::-1],m.pop(0)][x&1]

我对Python不太了解,非常感谢您的帮助。

UPD:如果更改逻辑,则会得到以下结果:

f=lambda m,x:m and([m.pop(0)[::-1],m.pop(0)][x&1])+f(m,x+1)
print(f([[4, 3, 2, 1], [5, 6, 7, 8], [12, 11, 10, 9], [13, 14, 15, 16]],0))

# [1, 2, 3, 4, 13, 14, 15, 16]

PS。高尔夫球代码(如果这很重要,则代码的本质是它以蛇的形式绕过二维数组)

解决方案:

[m.pop(0)[::-1],m.pop(0)][x&1] => (lambda: m.pop(0)[::-1], lambda: m.pop(0))[x&1]()

https://ideone.com/u6Qp4O

2 个答案:

答案 0 :(得分:2)

问题在于三元组if仅评估其分支之一,因此仅发生一个pop调用。在您的代码中,有两个pop调用都被评估。

[m.pop(0)[::-1], m.pop(0)][x&1]

为避免这种情况,如果必须以这种方式编写并且不使用三元组A if C else B,则必须对每种情况进行重击,lambda:,然后在对情况列表进行索引后,调用选择的情况:

[lambda: m.pop(0)[::-1], lambda: m.pop(0)][x&1]()

然后可以删除通用表达式:

item = m.pop(0)
[lambda: item[::-1], lambda: item][x&1]()

在进行重击之前执行此操作会导致:

item = m.pop(0)
[item[::-1], item][x&1]

如果项是可切片的,则不会产生错误。但这将无用地产生和丢弃项目的反向副本。但是,如果在x为奇数的情况下说int,而在偶数时说list则会导致错误:

>>> 3[::-1]
TypeError: 'int' object has no attribute '__getitem__'

因为表达式中的所有子表达式都将被求值,除非它们已被lambda延迟。

thunk是不带参数的函数的术语。

答案 1 :(得分:1)

给定表达式的所有三个版本之间的短路行为都不同(如果Query<Object1> q1 = currentSession.createQuery("from Object1 o where o.objectNumber= :objectNumber"); q1.setParameter("objectNumber", objectNumber); Object1 obj1 = q1.getSingleResult(); Query<Long> q2 = currentSession.createQuery("select count(id) from Object2 o where :object1param in elements(o.associatedObjects)); q2.setParameter("object1param ", obj1); 的某些元素为false)。 m惯用语通常在Python具有条件运算符之前使用,但是如果a and b or c为false则不适用。