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 docs on Expressions を見てください。これらはすべて、さまざまな複雑さの、何らかの種類の値を表すだけのものです。それらは、副作用を誘発するもの (I/O など) や可変データの変換ではありません。ジェネレーターは、その名前が示すように、単なる別の種類の式です。

コード行を減らすことは、ジェネレーター式の本来の目的ではありません。「メモリ効率と遅延計算された値」(以下のコメンターに感謝) の主な有用性を超えて、それらの目的の大部分は、イテレータをよりアクセスしやすい種類の原子値にすることで、コードをより簡潔で読みやすくすることです。コードの可読性を低下させている場合は、ジェネレーター式の使用が間違っている可能性があります。

特にジェネレータ式は、Python プログラミングの関数型パラダイムと密接に結びついているように思えます。例のように、数学的に定義されたシリーズから期待される値が得られますthe generator yielding all the Fibonacci numbers。この機能的パラダイムを念頭に置いて、特に副作用を生成するためにジェネレーターを使用することは、おそらくコードの匂いです。

ジェネレータ式を使用する正しい方法は、反復可能なデータセットの 1 つの要素に対して一度に 1 つの明確に定義された変換を実行し、後でその変換されたデータを生成することです。これは、関数パラダイムに適合します。つまり、関数は値を受け取り、値を返し、副作用はありません。

ジェネレーター関数を使用して、このコードを興味深い方法でリファクタリングし、生成された要素を反復して連続する要素を出力できるようにすることができます。そのようです:

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 に答える
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それを 1 行にすることができます。

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 に答える