32

次のようなものを書くことができるHaskellの「let」式に相当するPythonはありますか?

list2 = [let (name,size)=lookup(productId) in (barcode(productId),metric(size)) 
            for productId in list]

そうでない場合、最も読みやすい代替手段は何ですか?

let 構文を明確にするために追加されました。

x = let (name,size)=lookup(productId) in (barcode(productId),metric(size))

と同等です

(name,size) = lookup(productId)
x = (barcode(productId),metric(size))

ただし、2 番目のバージョンは、リスト内包表記ではうまく機能しません。

4

10 に答える 10

24

一時的なリスト内包表記を使用できます

[(barcode(productId), metric(size)) for name, size in [lookup(productId)]][0]

または、同等に、ジェネレータ式

next((barcode(productId), metric(size)) for name, size in [lookup(productId)])

しかし、どちらもかなりひどいです。

別の(恐ろしい)方法は、すぐに呼び出す一時的なラムダを使用することです

(lambda (name, size): (barcode(productId), metric(size)))(lookup(productId))

推奨される「Pythonic」の方法は、次のように関数を定義することだと思います

def barcode_metric(productId):
   name, size = lookup(productId)
   return barcode(productId), metric(size)
list2 = [barcode_metric(productId) for productId in list]
于 2012-08-31T16:52:46.437 に答える
20

最近の python バージョンでは、ジェネレーター式で複数の for 句を使用できるため、次のようなことができるようになりました。

list2 = [ barcode(productID), metric(size)
          for productID in list
          for (name,size) in (lookup(productID),) ]

これは、Haskell が提供するものにも似ています。

list2 = [ (barcode productID, metric size)
        | productID <- list
        , let (name,size) = lookup productID ]

と意味的に同等

list2 = [ (barcode productID, metric size) 
        | productID <- list
        , (name,size) <- [lookup productID] ]
于 2015-11-06T08:49:43.293 に答える
12

そのような事はありません。ラムダ計算( <=> )に脱糖されるのと同じ方法でエミュレートできます。letlet x = foo in bar(\x -> bar) (foo)

最も読みやすい代替手段は、状況によって異なります。あなたの特定の例として、私は次のようなものを選択します[barcode(productId), metric(size) for productId, (_, size) in zip(productIds, map(lookup, productIds))](考え直して本当に醜いです。必要がなければ簡単です。productId使用できますmap)または明示的なforループ(ジェネレーター内):

def barcodes_and_metrics(productIds):
    for productId in productIds:
        _, size = lookup(productId)
        yield barcode(productId), metric(size)
于 2012-08-31T16:51:05.103 に答える
9

b0fh's answer の複数の for 句は、私が個人的にしばらくの間使用してきたスタイルです。これにより、より明確になり、一時的な関数で名前空間が乱雑にならないと信じています。ただし、速度が問題になる場合は、要素が 1 つのリストを一時的に構築する方が、タプルを 1 つ構築するよりも著しく時間がかかることを覚えておくことが重要です。

このスレッドのさまざまなソリューションの速度を比較すると、醜いラムダ ハックが最も遅く、ネストされたジェネレーター、b0fh によるソリューションの順であることがわかりました。ただし、これらはすべて、1 タプルの勝者によって上回っていました。

list2 = [ barcode(productID), metric(size)
          for productID in list
          for (_, size) in (lookup(productID),) ]

これはOPの質問とはあまり関係がないかもしれませんが、ダミーイテレータのリストの代わりに1タプルを使用することで、リスト内包表記を使用したい場合に、明快さが大幅に向上し、速度が向上する他のケースがあります。

于 2016-01-24T15:10:36.527 に答える
4

Haskellが何をするかを推測するだけで、これが代替案です。Python で「リスト内包表記」として知られているものを使用します。

[barcode(productId), metric(size)
    for (productId, (name, size)) in [
        (productId, lookup(productId)) for productId in list_]
]

lambda:他の人が示唆しているように、の使用を含めることができます。

于 2012-08-31T16:56:14.520 に答える
3

漠然と比較できるものを得るには、2 つの内包表記またはマップを実行するか、新しい関数を定義する必要があります。まだ提案されていないアプローチの 1 つは、このように 2 行に分割することです。これはある程度読みやすいと思います。おそらく独自の関数を定義するのが正しい方法です。

pids_names_sizes = (pid, lookup(pid) for pid in list1)
list2 = [(barcode(pid), metric(size)) for pid, (name, size) in pids_names_sizes]
于 2012-08-31T17:14:49.497 に答える