web-dev-qa-db-ja.com

Python変数が先行するfor-inループ

foo = [x for x in bar if x.occupants > 1]

ここをグーグルで検索した後、これが何をするのか理解できませんでした。たぶん私は正しいものを探していなかったが、ここにある。この速記を暴く際のご意見は大歓迎です。

68
Greg Flynn

現在の答えは良いのですが、それらがどのように単に 構文糖 であるかについては話さないでください。

例から始めましょう。10個の数字があり、5個よりも大きい数字のサブセットが必要だとします。

_>>> numbers = [12, 34, 1, 4, 4, 67, 37, 9, 0, 81]
_

上記のタスクの場合、以下のアプローチは互いにまったく同じであり、最も詳細なものから簡潔で読みやすいものになりますPythonic

アプローチ1

_result = []
for index in range(len(numbers)):
    if numbers[index] > 5:
        result.append(numbers[index])
print result  #Prints [12, 34, 67, 37, 9, 81]
_

アプローチ2(少しきれいなfor-inループ)

_result = []
for number in numbers:
    if number > 5:
        result.append(number)
print result  #Prints [12, 34, 67, 37, 9, 81]
_

アプローチ3(リスト理解の入力)

_result = [number for number in numbers if number > 5]
_

またはより一般的に:

_[function(number) for number in numbers if condition(number)]
_

どこ:

  • function(x)xを受け取り、有用なものに変換します(たとえば、_x*x_など)
  • condition(x)がFalse-y値(False、None、空の文字列、空のリストなど)を返す場合、現在の反復はスキップされます(continueと考えてください)。関数がFalse-y以外の値を返す場合、現在の値は最終的な結果の配列になります(そして上記の変換ステップを経ます)。

少し異なる方法で構文を理解するには、以下のボーナスセクションをご覧ください。

詳細については、他のすべての回答がリンクしているチュートリアルに従ってください: List Comprehension


ボーナス

(わずかに非Pythonですが、完全を期すためにここに配置しています)

上記の例は次のように書くことができます。

_result = filter(lambda x: x > 5, numbers)
_

上記の一般式は次のように書くことができます。

_result = map(function, filter(condition, numbers)) #result is a list in Py2
_
63
UltraInstinct

リスト内包表記

fooは、属性占有者が1より大きいオブジェクトを含むbarのフィルター済みリストになります

barは、listsetdict、またはその他の反復可能なものにすることができます

ここに明確にする例があります

>>> class Bar(object):
...   def __init__(self, occupants):
...     self.occupants = occupants
... 
>>> bar=[Bar(0), Bar(1), Bar(2), Bar(3)]
>>> foo = [x for x in bar if x.occupants > 1]
>>> foo
[<__main__.Bar object at 0xb748516c>, <__main__.Bar object at 0xb748518c>]

Fooには2つのBarオブジェクトがありますが、どのオブジェクトであるかをどのように確認しますか? __repr__メソッドをBarに追加して、より参考になるようにします

>>> Bar.__repr__=lambda self:"Bar(occupants={0})".format(self.occupants)
>>> foo
[Bar(occupants=2), Bar(occupants=3)]
26
John La Rooy

これは、占有者が1より大きいbarのすべての要素を含むリストを返します。

0
Kien Truong

私が知る限り、これが機能する方法は、リスト「バー」が空(0)であるか、x.occupantsを介してシングルトン(1)で構成されているかを確認することです。居住者の特性があるかもしれません。したがって、fooは呼び出され、リスト内を移動し、x.occupantであるチェック条件に合格したすべてのアイテムを返します。

Javaのような言語では、「x」と呼ばれるクラスを作成し、「x」オブジェクトを配列などに割り当てます。 Xには「occupants」というフィールドがあり、各インデックスはx.occupantsメソッドでチェックされ、占有者に割り当てられた番号が返されます。そのメソッドが1より大きい値を返した場合(ここではintを部分的な占有者とみなします)、fooメソッド(問題の配列または類似のもので呼び出されます)は、fooメソッドで定義された配列または類似物を返しますこのコンテナ配列または何を持っています。返される配列の要素は、最初の配列のものの「x」オブジェクトであり、「1より大きい」という基準に適合します。

Pythonにはリスト内包表記を介した組み込みメソッドがあり、これをより簡潔で大幅に簡素化された方法で処理します。 2つの完全なクラスといくつかのメソッドを実装するのではなく、1行のコードを記述します。

0
World Engineer