我有一个词典列表:
dictlist = [{'key1':'value1', 'key2':'value2'}, {'key3':'value3', 'key4':'value4'}]
我目前打印像这样的键值对:
for d in dictlist:
for key in d:
print .format('{} ---> {}').format(key,d[key])
我如何使用生成器表达式来减少代码行?
编辑:我试图熟悉生成器表达式,而不仅仅是减少代码行!
答案 0 :(得分:3)
看看python docs on expressions。这些都只是代表各种复杂性的价值。它们不是副作用诱导事物(如I / O)或可变数据的转换。顾名思义,生成器表达式只是另一种表达式。
减少代码行不是生成器表达式的预期目的。除了“内存效率和懒惰计算值”的主要用途之外(感谢下面的评论者),他们的目的很大一部分是通过使迭代器成为更易于访问的原子值来使代码更简洁和可读。如果你的代码可读性较差,那么你可能错误地使用了生成器表达式。
特别是在我看来,生成器表达式与python编程的功能范例紧密相关。它们可以按照数学定义的系列产生值,例如the generator yielding all the Fibonacci numbers
。考虑到这个功能范例,使用生成器专门产生副作用可能是代码气味 。
为了正确地使用正确的方法来使用生成器表达式,可能是让它们一次对可迭代数据集的一个元素进行单个明确定义的转换,并产生转换后的数据然后。这符合功能范例:函数接受值,返回值,没有副作用。
您可以使用生成器函数以一种有趣的方式重构此代码,这将允许您通过迭代生成的元素来打印连续的元素。像这样:
def my_printer(dictlist):
for d int dictlist: # renamed to not shadow dict
for key in dict:
print .format('{} ---> {}').format(key,dict[key])
yield
然后你可以打印像:
这样的元素>>> p = my_printer(dictlist)
>>> p.next()
'some stuff 1'
>>> p.next()
'some stuff 2'
等
但这并不是你要求的。
要更直接地回答您的问题,如果您将print
语句从中删除,您可能会得到一些看似扁平的嵌套for
循环的内容:
>>> (('{} ---> {}').format(k,v) for d in dictlist for k,v in d.items())
或者实际上,由于(k,v)
只是一个元组,您传递的顺序相同,因此您可以使用splat运算符*
将其作为参数直接解压缩到format
调用中:
>>> (('{} ---> {}').format(*p) for d in dictlist for p in d.items())
最后,您可能希望使用d.items()
功能删除iteritems
的中间列表创建:
>>> (('{} ---> {}').format(*p) for d in dictlist for p in d.iteritems())
然后使用常规for循环打印结果:
>>> for x in _:
print x
key2 ---> value2
key1 ---> value1
key3 ---> value3
key4 ---> value4
答案 1 :(得分:2)
使代码水平而不是垂直没有任何实际好处,但您可以按如下方式执行:
from __future__ import print_function
from itertools import imap
print(*(' ---> '.join(imap(str, item)) for dic in dictlist for item in dic.iteritems()), sep='\n')
结果:
key2 ---> value2
key1 ---> value1
key3 ---> value3
key4 ---> value4
请注意,map()
用于将非字符串元素转换为字符串,以便它们可以与join()
结合使用。如果您确定键和值始终是字符串,则只需使用' ---> '.join(item)
代替。
答案 2 :(得分:1)
但是如果你想要一个更紧凑的版本,那么:
>>> dictlist = [{'key1':'value1', 'key2':'value2'}, {'key3':'value3', 'key4':'value4'}]
>>> list((k,v) for d in dictlist for k,v in d.iteritems())
[('key2', 'value2'), ('key1', 'value1'), ('key3', 'value3'), ('key4', 'value4')]
注意:最外面的list
只是一个占位符。你应该在其位置调用put函数调用。
答案 3 :(得分:0)
如果真的想要,你可以迭代生成本身的生成器表达式,然后丢弃你迭代的内容:
for _ in (print('{} ---> {}'.format(key,dict[key])) for dict in dictlist for key in dict):
pass
我真的没有理由这样做,但是,它不是很可读。它假设使用Python 3或from __future__ import print_function
,因此您可以在表达式中使用print
。
答案 4 :(得分:-1)
您可以使用生成器表达式并itertools
对其进行单行处理。
from itertools import chain, imap
print '\n'.join('{} ---> {}'.format(k,v) for k, v in chain.from_iterable(d.iteritems() for d in dictlist))
d.itervalues()
返回每个字典中所有值的生成器。 itertools.chain
获取所有这些生成器,并将它们展平为单个生成器。 itertools.imap
函数将所有值转换为字符串,因此可以打印它们。然后将这些值输入.join
方法,该方法在每个值之间放置一个换行符并打印出来。