Python

Python入門ガイド: 内包表記の使い方と応用例【どこよりも詳しく解説!!】

Pythonのリストは、複数の要素をまとめて扱うためのデータ構造です。この記事では、Pythonリストのコンテンツ表記(内包表記)の使い方を解説します。コンテンツ表記(内包表記)は、リストを簡潔に初期化する方法であり、効率的で読みやすいコードを作成するのに役立ちます。さらに、応用例を通じて実際の使用方法を理解していきましょう。

単純なリストの作成

リストを作成する最も基本的な方法は、角かっこ([])を使用して要素を指定することです。例えば、

numbers = [ 1, 2, 3, 4, 5]

というコードは、1から5までの数値が要素として含まれるリストを作成します。

範囲指定によるリストの作成

Pythonでは、範囲指定を使用して連続する数値のリストを作成することができます。例えば、

numbers = list(range(1, 6))

というコードは、1から5までの数値を要素とするリストを作成します。range関数は、指定した範囲の数値を生成するために使用されます。

条件付きコンテンツ表記

条件を組み合わせることで、特定の条件に基づいて要素を生成することもできます。例えば、

even_numbers = [x for x in range(1, 11) if x % 2 == 0]

というコードは、1から10までの数値のうち、偶数の要素を持つリストを作成します。条件式を組み合わせることで、さまざまな条件に基づいた要素の生成が可能です。

リスト内包表記

リスト内包表記は、リストを効率的に作成するための強力な手法です。現在では通常のforループよりも圧倒的に使用される機会が多いのでしっかり覚えてください。

リスト内包表記の基本構文

 リスト内包表記の基本構文を以下になります。

x = [リストの要素を計算する式 for 計算で使用する変数 in 反復可能オブジェクト]

 リスト内包表記では、「計算で使用する変数」に「反復可能オブジェクト」の要素が1つずつ渡され、それを使って(あるいは使うことなく)「リストの要素を計算する式」でリスト内包表記により作成されるリストの要素が算出されます。同じことをfor文で書くと次のようになります。

x = []
for 計算で使用する変数 in 反復可能オブジェクト:
    x.append(リストの要素を計算する式)

 このようにfor文では3行(以上)必要な処理がリスト内包表記なら1行で済み簡潔です。内包表記がどうなるか不安になったら、上に示したようにfor文ではどう書くかを考えてみると、対応するリスト内包表記が見えてきます。

リスト内包表記の使い方

  1. 要素の変換: リスト内の要素を変換することができます。例えば、
    squared_numbers = [x**2 for x in numbers]
    というコードは、numbersリストの各要素を2乗した値を持つリストを作成します。
  2. 複数のリストの組み合わせ: 複数のリストを組み合わせて新しいリストを作成することもできます。例えば、
    combined_list = [(x, y) for x in list1 for y in list2]
    というコードは、list1とlist2の要素の組み合わせをタプルとして持つリストを作成します。
  3. 条件付き要素の生成: 特定の条件に基づいて要素を生成することもできます。例えば、
    even_squares = [x**2 for x in numbers if x % 2 == 0]
    というコードは、numbersリストの偶数の要素を2乗した値を持つリストを作成します。
  4. 文字列操作: リスト内包表記は、文字列操作にも使用することができます。例えば、
    words = ['apple', 'banana', 'cherry']
    というリストがある場合、
    uppercase_words = [word.upper() for word in words]
    というコードは、各要素を大文字に変換したリストを作成します。

Pythonのリスト内包表記は、効率的で簡潔なコードを作成するための強力な手法です。単純なリストの初期化から条件付き要素の生成、複数のリストの組み合わせ、文字列操作など、さまざまな応用が可能です。リスト内包表記を使うことで、コードの可読性とメンテナンス性を向上させることができます。

リスト内包表記のサンプルコード

これまで書いてきた様にリスト内包表記は、多様な操作を行う事が可能です。以下に幾つかのサンプルを示します。

リスト内の数値を二乗する例

numbers = [ 1, 2, 3, 4, 5]

squared_numbers = [num ** 2 for num in numbers]
print(squared_numbers)

このコードでは、numbersリスト内の各要素を二乗し、新しいリストsquare_numbersに格納しています。要素を二乗した値がそれぞれ入ります。

文字列リスト内の要素を大文字に変換する例

fruits = ['apple', 'banana', 'orange']
capitalized_fruits = [fruit.upper() for fruit in fruits]
print(capitalized_fruits)

このコードでは、fruitsリスト内の各要素を大文字に変換し、新しいリストcapitalized_fruitsに格納しています。結果は[‘APPLE’, ‘BANANA’, ‘ORANGE’]となります。

リスト内の数値から偶数のみを抽出する例

numbers = [ 1, 2, 3, 4, 5 ]
even_numbers = [num for num in numbers if num % 2 == 0]
print(even_numbers)

このコードでは、numbersリスト内の各要素をチェックし、偶数のみを新しいリストeven_numbersに格納しています。

文字列リストから特定の文字で始まる要素を抽出する例

fruits = ['apple', 'banana', 'orange', 'kiwi', 'pear']
starts_with_a = [fruit for fruit in fruits if fruit.startswith('a')]
print(starts_with_a)

このコードでは、fruitsリスト内の各要素のなかで「’a’」から始まる要素を、starts_with_aに格納しています。結果は [‘apple’]となります。

2次元リストのフラット化

matrix = [[ 1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for sublist in matrix for num in sublist]
print(flattened)

このコードでは、matrixという2次元リストをflattenedという1次元配列へ変換しています。出力結果は [ 1, 2, 3, 4, 5, 6, 7, 8, 9]となります。

リスト内容表記を使用することで、より短くコンパクトなコードを記述することができます。これにより、処理を効率化し、可読性が向上していることが分かるかと思います。
リスト内包表記を使えば、ループや条件文を一行で表現することができます。

多次元のリストや辞書を対象としたリスト内包表記

内包表記は、単純なリストだけではなく、辞書など様々なものでも利用可能です。いくつかサンプルを記載します。

多次元リストの要素の合計を計算する例

matrix = [[ 1, 2, 3], [4, 5, 6], [7, 8, 9]]
sum_of_elements = sum([num for sublist in matrix for num in sublist])
print(sum_of_elements)

出力結果: 45

辞書の値を操作して新しい辞書を作成する例

prices = {'apple': 0.99, 'banana': 0.25, 'orange': 0.50, 'kiwi': 1.25, 'pear': 0.75}
discounted_prices = {item: price * 0.8 for item, price in prices.items()}
print(discounted_prices)

出力結果: {'apple': 0.792, 'banana': 0.2, 'orange': 0.4, 'kiwi': 1.0, 'pear': 0.6}

多次元リストの特定の条件を満たす要素のみを抽出する例

matrix = [[ 1, 2, 3], [4, 5, 6], [7, 8, 9]]
filtered_matrix = [[num for num in sublist if num % 2 == 0] for sublist in matrix]
print(filtered_matrix)

オブジェクトから特定の条件を満たす要素を抽出する例

class Car:
    def __init__(self, brand, color, price):
        self.brand = brand
        self.color = color
        self.price = price

# 車両リストの作成
cars = [
    Car('Toyota', 'Red', 20000),
    Car('Honda', 'Blue', 25000),
    Car('Ford', 'Black', 30000),
    Car('Toyota', 'White', 18000),
    Car('BMW', 'Black', 50000)
]

# 内包表記を使って特定の条件に合致する車両のみを抽出する
filtered_cars = [car for car in cars if car.brand == 'Toyota' and car.price <= 25000]

# 結果の表示
for car in filtered_cars:
    print(f"Brand: {car.brand}, Color: {car.color}, Price: {car.price}")

この例では、Carクラスを定義し、車両の情報を持つオブジェクトを作成します。それを含むリストを作成し、内包表記を使って特定の条件に合致する車両のみを抽出しています。この場合、Toyotaブランドかつ価格が25000以下の車両が結果として表示されます。

リスト内包表記の実践での活用

リスト内包表記の動きを理解するために簡単なアプリケーションを作ってみましょう!

import argparse

def parse_arguments():
    parser = argparse.ArgumentParser(description='Calculate absolute values of numbers')
    parser.add_argument('numbers', metavar='N', type=int, nargs='+', help='List of numbers')
    return parser.parse_args()

def calculate_absolute_values(numbers):
    absolute_values = [abs(num) for num in numbers]
    return absolute_values

def main():
    args = parse_arguments()
    numbers = args.numbers
    absolute_values = calculate_absolute_values(numbers)
    print(absolute_values)

if __name__ == '__main__':
    main()

サンプルコードを「absolute_value.py」という名前で保存してください。
ターミナルから python absolute_values.py 5 -2 3 -1 0 と実行してみてください。

$ python absolute_values.py 5 -2 3 -1 0
[5, 2, 3, 1, 0]

このサンプルコードは、ユーザーから数値のリストを受け取り、それらの数値の絶対値を計算して表示するものです。

argparse モジュールを使用してコマンドライン引数を解析しています。ユーザーはコマンドラインで複数の数値を指定し、それらの数値の絶対値が計算され、表示されます。

このサンプルコードは、リスト内包表記を使ってコマンドライン引数から取得した数値のリストを処理し、絶対値のリストを作成しています。リスト内包表記の使用により、処理が短くシンプルになっていることが分かります。

もう一つ作ってみましょう!!
次はジャンケンゲームです。以下にサンプルコードを記載するので写経してみてください。

import random

choices = ['rock', 'paper', 'scissors']
winning_conditions = [('rock', 'scissors'), ('paper', 'rock'), ('scissors', 'paper')]

user_choice = input("Your choice: ")
computer_choice = random.choice(choices)

result = "Draw" if user_choice == computer_choice else "You win!" if any(user_choice == w[0] and computer_choice == w for w in winning_conditions) else "Computer wins!"

print(f"Your choice: {user_choice}")
print(f"Computer's choice: {computer_choice}")
print(result)

あまり読み易くなりませんでしたね。1行が長くなり過ぎました。
この様に何でも無理に内包表記にすると、逆に可読性が悪くなる場合もあります。

状況によって使い分けてください。
ちなみにジャンケンゲームは次の様なコード形で書くと可読性が良いかも知れません。参考にしてみてください。

import random
import argparse

def parse_arguments():
    parser = argparse.ArgumentParser(description='Rock-Paper-Scissors game')
    parser.add_argument('choice', choices=['rock', 'paper', 'scissors'], help='Your choice: rock, paper, or scissors')
    return parser.parse_args()

def generate_computer_choice():
    choices = ['rock', 'paper', 'scissors']
    computer_choice = random.choice(choices)
    return computer_choice

def determine_winner(user_choice, computer_choice):
    winning_conditions = [('rock', 'scissors'), ('paper', 'rock'), ('scissors', 'paper')]
    if user_choice == computer_choice:
        return 'Draw'
    elif (user_choice, computer_choice) in winning_conditions:
        return 'You win!'
    else:
        return 'Computer wins!'

def main():
    args = parse_arguments()
    user_choice = args.choice
    computer_choice = generate_computer_choice()
    winner = determine_winner(user_choice, computer_choice)
    print(f'Your choice: {user_choice}')
    print(f'Computer\'s choice: {computer_choice}')
    print(winner)

if __name__ == '__main__':
    main()

このアプリケーションでは、argparse モジュールを使用してコマンドライン引数を解析しています。ユーザーはコマンドラインで自分の手の選択肢を指定し、それに対してコンピューターがランダムに手を選びます。その後、勝敗が判定され、結果が表示されます。

$ python rock_paper_scissors.py rock
Your choice: rock
Computer's choice: scissors
You win!

まとめ

Pythonのリスト内包表記は、効率的で簡潔なコードを作成するための強力な手法です。単純なリストの初期化から条件付き要素の生成、複数のリストの組み合わせ、文字列操作など、さまざまな応用が可能です。リスト内包表記を使うことで、コードの可読性とメンテナンス性を向上させることができます。

以上が、「Pythonリスト: コンテンツ表記の使い方と応用例」という記事の内容です。リスト内包表記を活用して効率的なコーディングを行い、Pythonプログラミングのスキルを向上させましょう。