効率的にPythonコードを書く方法:初心者向けチュートリアル

Pythonコードを効率的に書く方法:初心者向けチュートリアル

  

初心者プログラマーは、シンプルかつ読みやすい構文のPythonでコーディングを楽しんでいます。しかし、効率の良いPythonコードを書くには、思っている以上に複雑な作業が必要です。言語のいくつかの機能を理解する必要がありますが(それらは非常に簡単に習得できます)、このチュートリアルでは、C++やJavaScriptなど他のプログラミング言語から来た人々のために、効率的なPythonコードを書くためのいくつかのヒントを学ぶことができます。しかし、あなたが初心者であり、Pythonを最初の(プログラミング)言語として学んでいる場合、このチュートリアルでは最初からPythonicなコードを書くのに役立ちます。以下に注目します:

 

  • Pythonicなループ
  • リストと辞書内包表現
  • コンテキストマネージャー
  • ジェネレーター
  • コレクションクラス

それでは、さっそく始めましょう!

 

1. Pythonicなループを書く

 

ループ構文の理解は、どの言語でプログラミングしているかに関わらず重要です。C++やJavaScriptなどの言語から来た場合、Pythonicなループの書き方を学ぶと役に立ちます。

 

rangeを使って数列を生成する

 

range()関数は、しばしばループ内でイテレータとして使用される数列を生成します。

range()関数は、デフォルトで0から指定した数まで(指定した数は含まれない)の範囲オブジェクトを返します。

以下に例を示します:

for i in range(5):    print(i)

 

出力 >>> 01234

 

range()関数を使用する場合、必要に応じて開始点、終了点、ステップサイズをカスタマイズできます。

 

enumerateを使ってインデックスと要素にアクセスする

 

enumerate()関数は、イテラブル内の各要素のインデックスと値の両方にアクセスする必要がある場合に便利です。

この例では、インデックスを使用してfruitsリストにアクセスしています:

fruits = ["りんご", "ばなな", "さくらんぼ"]for i in range(len(fruits)):    print(f"インデックス {i}: {fruits[i]}")

 

出力 >>> インデックス 0: りんごインデックス 1: ばななインデックス 2: さくらんぼ

 

しかし、enumerate()関数を使用すると、次のようにインデックスと要素の両方にアクセスできます:

fruits = ["りんご", "ばなな", "さくらんぼ"]for i, fruit in enumerate(fruits):    print(f"インデックス {i}: {fruit}")

 

出力 >>> インデックス 0: りんごインデックス 1: ばななインデックス 2: さくらんぼ

 

zipを使って複数のイテラブルを並列に反復する

 

zip()関数は、複数のイテラブルを並列に反復するために使用されます。それは異なるイテラブルから対応する要素をペアにします。

次の例では、namesリストとscoresリストの両方をループで処理する必要があります:

names = ["アリス", "ボブ", "チャーリー"]scores = [95, 89, 78]for i in range(len(names)):    print(f"{names[i]}は{scoress[i]}点を獲得しました。")

 

これにより次のような出力が得られます:

出力 >>> アリスは95点を獲得しました。ボブは89点を獲得しました。チャーリーは78点を獲得しました。

 

これは、zip()関数を使用したはるかに読みやすいループです:

names = ["Alice", "Bob", "Charlie"]scores = [95, 89, 78]for name, score in zip(names, scores):    print(f"{name}は{score}ポイントを獲得しました。")

 

出力 >>>Aliceは95ポイントを獲得しました。Bobは89ポイントを獲得しました。Charlieは78ポイントを獲得しました。

 

zip()を使用したPythonicなバージョンは、手動でインデックス付けが必要ないため、コードがクリーンで読みやすくなります。

 

2. リストと辞書内包表記を使用する

 

Pythonでは、リスト内包表記と辞書内包表記がそれぞれリストと辞書を作成するための簡潔な1行コードです。条件付きステートメントを含めて、特定の条件に基づいてアイテムをフィルタリングすることもできます。

まず、ループバージョンからリストと辞書の内包表現に移動しましょう。

 

Pythonのリスト内包表記

 

numbersというリストがあるとします。そして、squared_numbersリストを作成したいとします。次のようなforループを使用できます:

numbers = [1, 2, 3, 4, 5]squared_numbers = []for num in numbers:    squared_numbers.append(num ** 2)print(squared_numbers)

 

出力 >>> [1, 4, 9, 16, 25]

 

しかし、リスト内包表記はこれを行うためのよりクリーンでシンプルな構文を提供します。イテラブルの各アイテムに対して式を適用して新しいリストを作成することができます。

  

ここでは、リスト内包表記を使用した簡潔な代替手法があります:

numbers = [1, 2, 3, 4, 5]squared_numbers = [num ** 2 for num in numbers]print(squared_numbers)

 

出力 >>> [1, 4, 9, 16, 25]

 

ここでは、リスト内包表記はnumbersリストの各数の二乗を含む新しいリストを作成します。

 

条件付きフィルタリング付きのリスト内包表記

 

リスト内包表記式内にフィルタリング条件を追加することもできます。次の例を考えてみましょう:

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

 

出力 >>> [1, 3, 5]

 

この例では、リスト内包表記はnumbersリストから奇数だけを含む新しいリストを作成します。

 

Pythonの辞書内包表記

 

リスト内包表記と似た構文を持つ辞書内包表記では、既存のイテラブルから辞書を作成することができます。

  

例えば、fruitsリストがあるとします。以下のようにfruit:len(fruit)というキーと値のペアを持つ辞書を作成したいとします。

以下のコードでこれを行う方法です:

fruits = ["apple", "banana", "cherry", "date"]fruit_lengths = {}for fruit in fruits:    fruit_lengths[fruit] = len(fruit)print(fruit_lengths)

出力 >>> {'apple': 5, 'banana': 6, 'cherry': 6, 'date': 4}

では、辞書内包表記の記述方法を書いてみましょう:

fruits = ["apple", "banana", "cherry", "date"]fruit_lengths = {fruit: len(fruit) for fruit in fruits}print(fruit_lengths)

出力 >>> {'apple': 5, 'banana': 6, 'cherry': 6, 'date': 4}

この辞書内包表記は、キーに果物、値に果物名の長さを持つ辞書を作成します。

条件付きフィルタリングを使用した辞書内包表記

辞書内包表記の式を変更して、条件を含めてみましょう:

fruits = ["apple", "banana", "cherry", "date"]long_fruit_names = {fruit: len(fruit) for fruit in fruits if len(fruit) > 5}print(long_fruit_names)

出力 >>> {'banana': 6, 'cherry': 6}

ここでは、辞書内包表記は、果物の名前をキーとし、果物名の長さを値とする辞書を作成しますが、名前が5文字より長い果物に対してのみ行います。

3. 効率的なリソースの扱い時にはコンテキストマネージャを使用する

Pythonのコンテキストマネージャは、リソースを効率的に管理するのに役立ちます。コンテキストマネージャを使用すると、リソースのセットアップとクリーンアップ(後始末)を簡単に行うことができます。最も単純で一般的なコンテキストマネージャの例は、ファイルの操作です。

以下のコードスニペットを見てみましょう:

filename = 'somefile.txt'file = open(filename,'w')file.write('Something')

これはファイルディスクリプタを閉じていないため、リソースの漏洩が起こります。

print(file.closed)出力 >>> False

以下のような方法を考えるかもしれません:

filename = 'somefile.txt'file = open(filename,'w')file.write('Something')file.close()

これはディスクリプタを閉じようとしますが、書き込み操作中に発生する可能性のあるエラーに対応していません。

さて、エラーのない状態でファイルを開き、何かを書き込んでみましょう:

filename = 'somefile.txt'file = open(filename,'w')try:    file.write('Something')finally:    file.close()

しかし、これは冗長です。以下は、コンテキストマネージャとしての機能を持つopen()関数を使用するwith文を使用したバージョンです:

filename = 'somefile.txt'with open(filename, 'w') as file:    file.write('Something')print(file.closed)

出力 >>> True

with文を使用してファイルが開かれるようになったコンテキストを作成します。この方法により、withブロックを抜けるときにファイルが正しく閉じられることが保証されます。例外が発生した場合でも同様です。

4. メモリ効率の高い処理のためにジェネレータを使用する

ジェネレータは、大きなデータセットや無限のシーケンスを扱うためのエレガントな方法を提供し、コードの効率を向上させ、メモリの消費量を低減します。

ジェネレータとは何ですか?

ジェネレータは、yieldキーワードを使用して値を一度に一つずつ返す関数であり、内部の状態を呼び出しの間で保持します。すべての値を一度に計算して完全なリストを返す通常の関数とは異なり、ジェネレータは要求されたときに計算と値を返すため、大きなシーケンスの処理に適しています。

 

ジェネレータはどのように動作しますか?

 

 

ジェネレータの動作方法を学びましょう:

  • ジェネレータ関数は、通常の関数と同じように定義されますが、returnキーワードではなく、yieldを使用して値を返します。
  • ジェネレータ関数を呼び出すと、ジェネレータオブジェクトが返されます。これは、ループを使用したり、next()を呼び出すことで繰り返すことができます。
  • yield文が出会うと、関数の状態が保存され、返された値が呼び出し元に戻ります。関数の実行は一時停止しますが、そのローカル変数と状態は保持されます。
  • ジェネレータのnext()メソッドが再度呼び出されると、一時停止した箇所から実行が再開され、次のyield文まで関数が続行されます。
  • 関数が終了するかStopIteration例外を発生させると、ジェネレータは消費されたと見なされ、next()の追加の呼び出しはStopIterationを発生させます。

 

ジェネレータの作成

 

ジェネレータは、ジェネレータ関数またはジェネレータ式を使用して作成できます。

以下はジェネレータ関数の例です:

def countdown(n):    while n > 0:        yield n        n -= 1# ジェネレータ関数を使用して使用するfor num in countdown(5):    print(num)

 

出力 >>> 5 4 3 2 1

 

ジェネレータ式はリスト内包表記と似ていますが、リストの代わりにジェネレータを作成します。

# ジェネレータ式を使用して正方形のシーケンスを作成するsquares = (x ** 2 for x in range(1, 6))# ジェネレータ式を使用して使用するfor square in squares:    print(square)

 

出力 >>> 1 4 9 16 25

 

5. コレクションクラスの活用

 

このチュートリアルでは、2つの便利なコレクションクラスについて学びます:

  • NamedTuple
  • Counter

 

NamedTupleを使用したより読みやすいタプル

 

Pythonでは、collectionsモジュールnamedtupleは、組み込みのタプルクラスのサブクラスですが、名前付きフィールドを提供します。これにより、通常のタプルよりも読みやすく、自己記述的になります。

以下は3D空間の点のための単純なタプルを作成し、個々の要素にアクセスする例です:

# 3Dポイントのタプルcoordinate = (1, 2, 3)# タプル展開を使用してデータにアクセスするx, y, z = coordinateprint(f"X座標:{x}、Y座標:{y}、Z座標:{z}")

 

出力 >>> X座標:1、Y座標:2、Z座標:3

 

そして、namedtupleバージョンです:

from collections import namedtuple# Coordinate3Dという名前のnamedtupleを定義Coordinate3D = namedtuple("Coordinate3D", ["x", "y", "z"])# Coordinate3Dオブジェクトを作成するcoordinate = Coordinate3D(1, 2, 3)print(coordinate)# 名前付きフィールドを使用してデータにアクセスするprint(f"X座標:{coordinate.x}、Y座標:{coordinate.y}、Z座標:{coordinate.z}")

 

出力 >>>Coordinate3D(x=1, y=2, z=3)X座標:1、Y座標:2、Z座標:3

 

NamedTuplesは、通常のタプルよりもクリーンで保守しやすいコードを記述することができるようにします。

 

Counterを使用してカウントを簡素化する

 

Counterは、collectionsモジュールのクラスであり、リストや文字列などのイテラブルな要素の頻度を数えるために設計されています。 {要素:頻度}のキーと値のペアを持つCounterオブジェクトを返します。

長い文字列での文字の頻度をカウントする例を見てみましょう。

以下は、ループを使用して文字の頻度をカウントする従来の方法です:

word = "incomprehensibilities"# 文字をカウントするための空の辞書を初期化char_counts = {}# 文字の頻度をカウントするfor char in word:    if char in char_counts:        char_counts[char] += 1    else:         char_counts[char] = 1# char_countsの辞書を出力するprint(char_counts)# 最も一般的な文字を見つけるmost_common = max(char_counts, key=char_counts.get)print(f"最も一般的な文字:'{most_common}'({char_counts[most_common]}回出現)")

 

文字列を手動で反復処理し、辞書を更新して文字の頻度をカウントし、最も一般的な文字を見つけます。

出力 >>>{'i': 5, 'n': 2, 'c': 1, 'o': 1, 'm': 1, 'p': 1, 'r': 1, 'e': 3, 'h': 1, 's': 2, 'b': 1, 'l': 1, 't': 1}最も一般的な文字:'i'(5回出現)

 

次に、同じタスクをCounterクラスを使って行いましょう。構文はCounter(iterable)です:

from collections import Counterword = "incomprehensibilities"# Counterを使って文字の頻度をカウントchar_counts = Counter(word)print(char_counts)# 最も一般的な文字を見つけるmost_common = char_counts.most_common(1)print(f"最も一般的な文字:'{most_common[0][0]}'({most_common[0][1]}回出現)")

 

出力 >>>Counter({'i': 5, 'e': 3, 'n': 2, 's': 2, 'c': 1, 'o': 1, 'm': 1, 'p': 1, 'r': 1, 'h': 1, 'b': 1, 'l': 1, 't': 1})最も一般的な文字:'i'(5回出現)

 

したがって、Counterを使用することで、手動で反復処理や辞書の管理が必要なく、文字の頻度を簡単にカウントする方法が提供されます。

 

まとめ

 

Pythonのツールボックスに追加できる便利なヒントをいくつか見つけられたことを願っています。Pythonを学びたい方やコーディング面接の準備をしている方には、以下のリソースが役立つでしょう:

学習を楽しんでください!

  

[Bala Priya C](https://twitter.com/balawc27)は、インド出身の開発者兼テクニカルライターです。彼女は数学、プログラミング、データサイエンス、コンテンツ作成の交差点での作業が好きです。彼女の関心と専門知識の範囲には、DevOps、データサイエンス、自然言語処理が含まれます。彼女は読書、執筆、コーディング、そしてコーヒーを楽しんでいます!現在、彼女はチュートリアル、ハウツーガイド、オピニオン記事などを執筆して、開発者コミュニティと彼女の知識を共有するために取り組んでいます。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

データサイエンス

アステラソフトウェアのCOO、ジェイ・ミシュラ - インタビューシリーズ

ジェイ・ミシュラは、急速に成長しているエンタープライズ向けデータソリューションの提供企業であるAstera Softwareの最高執...

人工知能

「Ami Hever、UVeyeの共同創設者兼CEO - インタビューシリーズ」

עמיר חבר הוא המנכל והמייסד של UVeye, סטארט-אפ ראיה ממוחשבת בלמידה עמוקה, המציבה את התקן הגלובלי לבדיקת רכבים עם זיהוי...

人工知能

「クリス・サレンス氏、CentralReachのCEO - インタビューシリーズ」

クリス・サレンズはCentralReachの最高経営責任者であり、同社を率いて、自閉症や関連する障害を持つ人々のために優れたクラ...

人工知能

ムーバブルインクのCEO兼共同創設者であるヴィヴェク・シャルマ氏についてのインタビュー・シリーズ

ビヴェクは2010年にムーバブルインクを共同設立し、急速な成長を遂げながら、600人以上の従業員を擁し、世界有数の革新的なブ...

人工知能

「リオール・ハキム、Hour Oneの共同創設者兼CTO - インタビューシリーズ」

「Hour Oneの共同創設者兼最高技術責任者であるリオール・ハキムは、専門的なビデオコミュニケーションのためのバーチャルヒ...

データサイエンス

「2023年にデータサイエンスFAANGの仕事をゲットする方法は?」

データサイエンスは非常に求められる分野となり、FAANG(Facebook、Amazon、Apple、Netflix、Google)企業での就職は大きな成...