Python の内包表記を覚えました

Python の内包表記は、他の言語から入ってくると独特に感じます。 だけど、便利なので、書いておきます。

環境

  • Python 3.6

5.1.3. List Comprehensions

List comprehensions provide a concise way to create lists. Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable, or to create a subsequence of those elements that satisfy a certain condition.

For example, assume we want to create a list of squares, like:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

5.1.3. List Comprehensions

リスト内包表記は、リストを作成する簡単な方法を提供してくれるようです。 引用にあるような for でリストを作成するような処理は、次の引用のように記述することができるみたいです。

Note that this creates (or overwrites) a variable named x that still exists after the loop completes. We can calculate the list of squares without any side effects using:

squares = list(map(lambda x: x**2, range(10)))

or, equivalently:

squares = [x**2 for x in range(10)]

which is more concise and readable.

5.1.3. List Comprehensions

下側の [] で囲んだものがリスト内包表記です。 [] で囲んで [... for ... in ...] のように記述すると、リスト内包表記になるみたいです。 リスト内包表記は簡潔で可読性が高いと記載されています。

A list comprehension consists of brackets containing an expression followed by a for clause, then zero or more for or if clauses. The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it. For example, this listcomp combines the elements of two lists if they are not equal:

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

5.1.3. List Comprehensions

入れ子にすることもできるようです。 xy が一致しない組み合わせのタプルのリストを作っているようです。 リスト内包表記でリストを作るときに if で条件をつけることもできるようです。

これは、次のように記述したものと同じようです。

and it’s equivalent to:

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Note how the order of the for and if statements is the same in both these snippets.

5.1.3. List Comprehensions

どちらも for の記述が先で、 if の記述が後ろって記載されています。 重要なのかな。

If the expression is a tuple (e.g. the (x, y) in the previous example), it must be parenthesized.

>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
  File "<stdin>", line 1, in <module>
    [x, x**2 for x in range(6)]
               ^
SyntaxError: invalid syntax
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

5.1.3. List Comprehensions

式がタプルの場合は、 (x, y) のように () で囲むようです。

List comprehensions can contain complex expressions and nested functions:

>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

5.1.3. List Comprehensions

リスト内包表記には、複雑な式やネストされた関数を含めることができるようです。

Python の range(n, n) って便利です。 JavaScript にも言語仕様として range 入ってこないのかな。

5.4. Sets

Similarly to list comprehensions, set comprehensions are also supported:

>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}

5.4. Sets

Python には、配列じゃないですけど、データのまとまりとして Set というものがあるようです。 Set は重複要素のない順不同の集合のようです。 それも、リスト内包表記と同じように、セット内包表記ができるようです。 {} で囲んで、 {... for ... in ...} のように記述すると、セット内包表記になるようです。

5.5. Dictionaries

In addition, dict comprehensions can be used to create dictionaries from arbitrary key and value expressions:

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

5.5. Dictionaries

辞書 (Dictionary) も内包表記ができるようです。 セット内包表記と同じで、 {} で囲むようです。 {...: ... for ... in ...} のように、 for の前に key: value のように、セミコロンでキーと値を記述するところが違うようです。

終わり

Python の内包表記について、次の 3 つを記載してみました。

  • リスト内包表記
  • セット内包表記
  • 辞書内包表記

COBOL, Java, VB.NET, JavaScript, C#, Ruby なんかを使ってきて、独特の記述のように感じました。 でも、この言語の文化のようですし、 for を使うよりも速いみたいなので、うまく使っていきたいと思います。

参考