Python for-in 循环前面有一个变量
Posted
技术标签:
【中文标题】Python for-in 循环前面有一个变量【英文标题】:Python for-in loop preceded by a variable 【发布时间】:2011-06-25 01:58:58 【问题描述】:foo = [x for x in bar if x.occupants > 1]
在谷歌搜索和搜索后,无法弄清楚这是做什么的。也许我没有寻找正确的东西,但它就在这里。非常感谢揭穿这种速记的任何意见。
【问题讨论】:
@Greg,我用谷歌搜索了python "* for * in * if"
,这是secnetix.de/olli/Python/list_comprehensions.hawk的第一次点击
【参考方案1】:
当前的答案很好,但不要谈论它们如何只是syntactic sugar 对我们如此习惯的某些模式。
让我们从一个例子开始,假设我们有 10 个数字,我们想要一个大于 5 的数字的子集。
>>> numbers = [12, 34, 1, 4, 4, 67, 37, 9, 0, 81]
对于上述任务,以下方法完全相同,从最冗长到简洁、易读和pythonic:
方法一
result = []
for index in range(len(numbers)):
if numbers[index] > 5:
result.append(numbers[index])
print result #Prints [12, 34, 67, 37, 9, 81]
方法 2(更简洁的 for-in 循环)
result = []
for number in numbers:
if number > 5:
result.append(number)
print result #Prints [12, 34, 67, 37, 9, 81]
方法3(输入列表理解)
result = [number for number in numbers if number > 5]
或更笼统地说:
[function(number) for number in numbers if condition(number)]
地点:
function(x)
接受 x
并将其转换为有用的东西(例如:x*x
)
如果condition(x)
返回任何 False-y 值(False、None、空字符串、空列表等),则将跳过当前迭代(想想continue
)。如果函数返回一个非 False-y 值,则当前值将成为最终结果数组(并经过上述转换步骤)。
要以稍微不同的方式理解语法,请查看下面的奖励部分。
有关更多信息,请按照所有其他答案链接的教程进行操作:List Comprehension
奖金
(有点不像pythonic,但为了完整起见将其放在这里)
上面的例子可以写成:
result = filter(lambda x: x > 5, numbers)
上面的一般表达式可以写成:
result = map(function, filter(condition, numbers)) #result is a list in Py2
【讨论】:
我通常将第一件事称为表达式;如果只是x*x
,它通常可能就在那里,而不是square(x)
。当我看到该表达式被封装成 lambda 时,它变得更加痛苦,例如[x**2 for x in range(5)]
与 map(lambda x: x**2, range(5))
.
list comprehension
而不将其存储在 var 中:[print(i) for i in numbers]
@Timo:虽然你的建议有效,但它不被接受。我个人讨厌它。 for
左侧的表达式(在您的情况下为 print(i)
)应该是不会引入像 I/O 之类的副作用的表达式(查找纯函数)。正如答案所呼唤的那样-它旨在用作“转换”,仅此而已。如果您要做的是打印,则打印列表推导的结果或使用普通的旧 for 循环来打印单个项目。【参考方案2】:
这是list comprehension
foo
将是 bar
的过滤列表,其中包含属性 occupants > 1 的对象
bar
可以是 list
、set
、dict
或任何其他可迭代对象
这是一个澄清的例子
>>> class Bar(object):
... def __init__(self, occupants):
... self.occupants = occupants
...
>>> bar=[Bar(0), Bar(1), Bar(2), Bar(3)]
>>> foo = [x for x in bar if x.occupants > 1]
>>> foo
[<__main__.Bar object at 0xb748516c>, <__main__.Bar object at 0xb748518c>]
所以 foo 有 2 个 Bar
对象,但是我们如何检查它们是哪些?让我们在Bar
中添加一个__repr__
方法,以便提供更多信息
>>> Bar.__repr__=lambda self:"Bar(occupants=0)".format(self.occupants)
>>> foo
[Bar(occupants=2), Bar(occupants=3)]
【讨论】:
这个答案比公认的答案要好,但由于它在 4 分钟后出现,所以没有标记为这样。【参考方案3】:由于问题的编程部分已被其他人完全回答,因此很高兴知道它与数学的关系(set theory)。其实是Python implementation of Set builder notation:
通过axiom of specification定义一个集合:
B = x є A : S(x)
英文翻译:B是一个集合,其成员选自A, 所以 B 是 A (B ⊂ A) 的子集,其中特征由 函数 S 成立:
S(x) == True
使用列表推导定义 B:
B = [x for x in A if S(x)]
所以要使用 list comprehension 构建 B,B 的成员(由 x 表示)从集合 中选择>A其中S(x) == True
(包含条件)。
注意:返回布尔值的函数S
称为predicate。
【讨论】:
【参考方案4】:这将返回一个列表,其中包含 bar 中居住者 > 1 的所有元素。
【讨论】:
【参考方案5】:据我所知,这应该起作用的方式是检查列表“栏”是否为空 (0) 或通过 x.occupants 由单例 (1) 组成,其中 x 是列表栏和可能具有居住者的特征。所以 foo 被调用,在列表中移动,然后返回所有通过检查条件的项目,即 x.occupant。
在像 Java 这样的语言中,您将构建一个名为“x”的类,然后将“x”对象分配给一个数组或类似的对象。 X 将有一个名为“occupants”的字段,并且将使用 x.occupants 方法检查每个索引,该方法将返回分配给 occupant 的数字。如果该方法返回大于 1(我们假设这里的 int 作为部分占用者会很奇怪。) foo 方法(在数组上调用或类似的问题。)然后将返回一个数组或类似的数组,如 foo 方法中定义的那样对于这个容器阵列或你有什么。返回数组的元素将是第一个数组中符合“大于 1”标准的“x”对象。
Python 有通过列表推导的内置方法以更简洁和大大简化的方式处理这个问题。我没有实现两个完整的类和几个方法,而是编写了一行代码。
【讨论】:
查看我添加到答案中的示例以上是关于Python for-in 循环前面有一个变量的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript学习总结(变量for和for-in循环)