2011-02-27 232 views
1

我试图找出在for循环语法中将参数从一个列表或字典传递给另一个的语法。从Python中的for循环返回值

期望的结果我在寻找的是:

for bean in beans: 
    if bean.type == 'coffee': 
    print bean 

只,而不是打印到stdout,我想收集字符串数据并将其追加到另一个列表。最终将名单弄平。

踢球者,我想在一条线上执行此操作。

我知道''.join()方法,我正在寻找这个结果,所以我可以过滤for-in循环的结果。

回答

10
[bean for bean in beans if bean.type == 'coffee'] 

List comprehensions很整齐。甚至整洁,通常你不需要产生一个完整的列表 - 你只需要一个迭代器,它给你列表将包含的值。这是一个生成器,可以通过生成器表达式简洁地表达它们。除了方括号变成parens(并且如果它是函数调用中唯一的参数,你可以忽略它们),它们的写法与列表解析相同。 '\n'.join(str(bean) for bean in beans if bean.type == 'coffee')。优点是提到的懒惰,也就是说,除非真正需要(请求),否则不会产生值,并且不会同时将所有值保存在内存中(除非消费者这样做)。

您可以使用itertools.chain将多个迭代(包括列表)链接到一个,或者如果您无法更改列表中的列表,则可以使用(x for list in lists for x in list)。对于涉及abritary深嵌套的一般化解决方案,您需要使用递归的全功能。

+1

由于列表是内置的,因此可能希望避免使用具有相同名称的变量。 – 2011-02-27 20:04:39

+1

@Adeel:通常是真的(如果你提出了一个好建议,我会编辑 - 除了非常神秘的'xs'外,我想不出任何通用名称)。虽然这里没有问题,但由于生成器表达式不会将迭代变量泄漏到外部(现在)。 – delnan 2011-02-27 20:53:26

+0

你完全正确地使用Python 3修正列表解析中循环控制变量的泄漏。只有我们这些仍在使用Python 2的人不得不担心这个问题。 – 2011-02-28 21:06:30

1
'\n'.join([str(bean) for bean in beans if bean.type == 'coffee']) 
+1

您可以跳过[]并获取生成器表达式。这避免了构建中间列表。 – Macke 2011-02-27 19:10:15

+0

@Macke,够了。我远离Python解释器,并不想冒str.join()没有迭代 - 我以前曾经被列表中的东西咬过。然后再次,这可能是.Net污染我的大脑...... – 2011-02-27 19:14:45

+0

请放心,在Python中,所有可能可以接受abritary iterables的东西都会。除非当然不是一个可怜的灵魂写的,因为他不知道谁在范围内(len(list))......是不可能的...... – delnan 2011-02-27 19:16:14

6

一个班轮将使用列表或发电机的理解,请参阅布莱尔的答案。

您当前密码的适应会适合yield关键字,它可以构建一个发生器功能是这样的:

def coffee_filter(beans): 
    for bean in beans: 
     if bean.type == 'coffee': 
      yield bean 

for bean in coffee_filter(beans): 
    print "coffee from %s" % bean.country 

因为Python可以让你几乎任何地方定义函数,这是非常有用的。

+1

编写一个完整的生成器在90%的情况下都是过度的。这也不例外。如果一个生成器表达式有效,就这样。 – delnan 2011-02-27 19:17:02

+1

我有点惊讶,你没有使用生成器表达式作为你的方法的内部。我不建议摆脱这个功能 - 如果没有其他的东西,它会根据它的名字提供文档(这很可爱,并且即使你的答案质量较差也会给你+1) – 2011-02-27 19:17:15

+0

+ 1添加材料阅读,谢谢队友。 – jbcurtin 2011-02-27 19:19:50