1

我有一个字典列表:

dictlist = [{'key1':'value1', 'key2':'value2'}, {'key3':'value3', 'key4':'value4'}]

我目前打印这样的键值对:

for d in dictlist:
  for key in d:
    print .format('{} ---> {}').format(key,d[key])

我将如何使用生成器表达式来减少代码行数?

编辑:我试图让自己熟悉生成器表达式,而不仅仅是减少代码行!

4

5 回答 5

3

查看有关表达式的 python 文档。这些都是仅代表一种或另一种、各种复杂性的值的东西。它们不是引起副作用的事物(如 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
于 2016-05-26T22:10:50.030 回答
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)

于 2016-05-26T21:47:28.757 回答
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')]

注意:Outermostlist只是一个占位符。你应该调用 put 一个函数调用来代替它。

于 2016-05-26T21:47:55.880 回答
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在表达式中使用。

于 2016-05-26T22:00:58.390 回答
-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在每个值之间放置换行符并打印它的方法。

于 2016-05-26T21:47:21.830 回答