Python & AI Tutorials Logo
Python プログラミング

19. 関数の定義と呼び出し

19.1) 関数とは何か、なぜ重要なのか

関数(function) とは、特定のタスクを実行するための、名前付きのコードブロックです。この本を通して、すでに print()input()len()type() など、たくさんの関数を使ってきました。これらは Python が提供する 組み込み関数(built-in functions) です。これからは、コードを整理し再利用できるようにするために、自分で カスタム関数(custom functions) を作る方法を学びます。

なぜ関数が重要なのか

関数は、読みやすく保守しやすいプログラムを書くうえで基礎となるものです。関数には、いくつかの重要な利点があります。

1. コードの再利用性

関数がなければ、タスクを実行したいたびに同じコードをコピー&ペーストする必要があります。たとえば、複数箇所で長方形の面積を計算する場合を考えてみましょう。

python
# 関数なし - 繰り返しのコード
length1 = 5
width1 = 3
area1 = length1 * width1
print(f"Area 1: {area1}")
 
length2 = 8
width2 = 4
area2 = length2 * width2
print(f"Area 2: {area2}")
 
length3 = 10
width3 = 6
area3 = length3 * width3
print(f"Area 3: {area3}")

Output:

Area 1: 15
Area 2: 32
Area 3: 60

この繰り返しは面倒で、ミスも起こりやすくなります。面積の計算方法を変更する必要がある場合(たとえば単位や丸めを含めるなど)、すべての箇所を更新しなければなりません。関数は、コードを一度だけ書いて何度も使えるようにすることで、この問題を解決します。

2. コードの整理

関数は、大きなプログラムを小さく扱いやすい部品に分割します。各関数が1つの特定のタスクを担当するため、コードが理解しやすく、保守もしやすくなります。何百行もある長いスクリプト1本にする代わりに、関連する処理を、目的が明確に伝わる名前付きの関数として整理できます。

3. 抽象化(abstraction)

関数は、実装の詳細をシンプルなインターフェースの背後に隠します。len(my_list) を呼び出すとき、Python がどうやって要素数を数えているかを知る必要はなく、結果だけが得られます。同様に、自分の関数も複雑な操作に対して簡単なインターフェースを提供でき、コードを使いやすく理解しやすくできます。

4. テストとデバッグ(debugging)

関数を使うと、プログラムの個々の部分をテストしやすくなります。大きなプログラムに組み込む前に、各関数が単独で正しく動くかを確認できます。何か問題が起きたときも、関数があると問題の発生箇所を絞り込みやすくなります。

この章の残りでは、自分の関数を定義し、情報を渡し、結果を受け取り、わかりやすくドキュメント化する方法を学びます。これらのスキルは、プロフェッショナルな Python コードを書くために不可欠です。

19.2) def による関数の定義

Python で関数を作るには、def キーワード("define" の略)を使います。関数定義の基本構造は次のとおりです。

python
def function_name():
    # 関数が呼び出されたときに実行されるコードブロック
    statement1
    statement2
    # ... さらに文が続く

それぞれの要素を分解してみましょう。

  • def: 関数を定義していることを Python に伝えるキーワード
  • function_name: 関数に付ける名前(変数名と同じルールに従います)
  • (): いずれパラメータ(parameters)を入れる括弧(次のセクションで扱います)
  • :: 関数ヘッダーの終わりを示すコロン
  • インデントされたコードブロック: 関数本体を構成する文(インデントが必須)

最初の関数

挨拶を表示するシンプルな関数はこちらです。

python
def greet():
    print("Hello!")
    print("Welcome to Python functions.")
 
# Call the function
greet()

Output:

Hello!
Welcome to Python functions.

関数を定義しても、Python はそれを記憶するだけで、内部のコードをすぐには実行しません。コードが実行されるのは、関数名の後に括弧を付けて greet() のように書き、関数を 呼び出す(call) ときだけです。

関数の命名規則

関数名は、(第3章で学んだように)変数名と同じルールに従います。

  • 小文字を使う
  • 単語はアンダースコアで区切る(snake_case)
  • 数字ではなく、文字かアンダースコアで始める
  • 関数が何をするかがわかる説明的な名前にする
python
# 良い関数名
def calculate_total():
    pass
 
def get_user_age():
    pass
 
def display_menu():
    pass
 
# 良くない関数名(ただし文法的には正しい)
def x():  # 説明的ではない
    pass
 
def CalculateTotal():  # 小文字を使うべき
    pass
 
def calc():  # 省略しすぎ
    pass

: ここでは pass をプレースホルダーとして使っています(第8章で学びました)。pass 自体は何もしませんが、関数定義を文法的に完結させます。

関数にはどんなコードでも書ける

関数の本体には、これまで学んだあらゆる Python 文を入れられます。変数への代入、条件分岐、ループ(loop)、さらには別の関数の呼び出しも可能です。

python
def check_temperature():
    temperature = 72
    if temperature > 75:
        print("It's warm.")
    elif temperature > 60:
        print("It's comfortable.")
    else:
        print("It's cool.")
 
check_temperature()

Output:

It's comfortable.

複数の関数定義

プログラム内では必要なだけ関数を定義できます。各関数は独立しており、それぞれ別々に呼び出せます。

python
def morning_greeting():
    print("Good morning!")
 
def evening_greeting():
    print("Good evening!")
 
# Call each function
morning_greeting()
evening_greeting()

Output:

Good morning!
Good evening!

関数定義の順序

Python では、関数は呼び出す前に定義しておく必要があります。Python インタープリタはコードを上から下へ読み取るため、定義前に関数を呼び出そうとするとエラーになります。

python
# WARNING: This will cause a NameError - for demonstration only
# PROBLEM: Function called before it's defined
say_hello()  # NameError: name 'say_hello' is not defined
 
def say_hello():
    print("Hello!")

正しい順序は、先に定義してから呼び出すことです。

python
# Correct: Define first
def say_hello():
    print("Hello!")
 
# Then call
say_hello()

Output:

Hello!

ただし、ファイル内の後ろで定義される関数を、別の関数が呼び出すことは可能です。すべての定義が終わった後にその呼び出しが実行される限りは問題ありません。

python
def first_function():
    print("First function")
    second_function()  # これは問題ありません - 実行時に呼び出されます
 
def second_function():
    print("Second function")
 
# 最初の関数を呼び出す前に、両方の関数が定義されています
first_function()

Output:

First function
Second function

関数はローカルスコープを作る

関数の中で作成された変数は、その関数の中でのみ存在します。これは ローカルスコープ(local scope) と呼ばれます(詳しくは第21章で扱います)。いまは、関数の中で起きたことは関数の中に留まる、と理解しておいてください。

python
def create_message():
    message = "This is local"
    print(message)
 
create_message()
 
# This would cause an error:
# print(message)  # NameError: name 'message' is not defined

Output:

This is local

変数 message は、関数が実行されている間だけ存在します。関数が終了すると、その変数は消えます。

pass を使った空の関数

ときには、関数の枠組みだけを先に定義して、実装は後から行いたい場合があります。そのときは pass をプレースホルダーとして使います。

python
def future_feature():
    pass  # TODO: 後でこれを実装する
 
# 関数は存在し呼び出せますが、何もしません
future_feature()  # Runs without error, does nothing

これは、細部を埋める前にプログラムの構造をスケッチするときに役立ちます。

19.3) 関数の呼び出しと引数の受け渡し

関数を定義すると再利用可能なコードの部品が作れますが、関数を本当に強力にするには情報を渡す必要があります。この情報は 引数(arguments) を通して渡されます。

パラメータと引数の違い

続ける前に、よく混同される2つの用語をはっきりさせておきましょう。

  • パラメータ(parameter): 関数定義の中にある、値を受け取る変数名
  • 引数(argument): 関数を呼び出すときに渡す実際の値
python
def greet(name):  # 'name' はパラメータ
    print(f"Hello, {name}!")
 
greet("Alice")  # "Alice" は引数

Output:

Hello, Alice!

パラメータはプレースホルダー、引数はそのプレースホルダーを埋める実データだと考えるとよいでしょう。

パラメータ付き関数の定義

入力を受け取る関数を定義するには、括弧の中にパラメータ名を追加します。

python
def greet_person(name):
    print(f"Hello, {name}!")
    print("Nice to meet you.")
 
# Call with different arguments
greet_person("Alice")
print()  # Blank line for readability
greet_person("Bob")

Output:

Hello, Alice!
Nice to meet you.
 
Hello, Bob!
Nice to meet you.

パラメータ name は関数内で変数として振る舞います。関数を呼び出すたびに、name は渡された引数の値を取ります。

複数のパラメータ

関数は、カンマで区切ることで複数のパラメータを受け取れます。

python
def calculate_rectangle_area(length, width):
    area = length * width
    print(f"A rectangle with length {length} and width {width}")
    print(f"has an area of {area} square units.")
 
calculate_rectangle_area(5, 3)
print()
calculate_rectangle_area(10, 7)

Output:

A rectangle with length 5 and width 3
has an area of 15 square units.
 
A rectangle with length 10 and width 7
has an area of 70 square units.

複数のパラメータを持つ関数を呼び出すときは、順序が重要です。最初の引数は最初のパラメータへ、2番目の引数は2番目のパラメータへ、というように割り当てられます。これを 位置引数(positional arguments) と呼びます。

位置引数

位置引数では、Python は位置に基づいて引数をパラメータに対応付けます。

python
def describe_pet(animal_type, pet_name):
    print(f"I have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name}.")
 
describe_pet("dog", "Buddy")
print()
describe_pet("cat", "Whiskers")

Output:

I have a dog.
My dog's name is Buddy.
 
I have a cat.
My cat's name is Whiskers.

順序を取り違えると、想定外の結果になります。

python
def describe_pet(animal_type, pet_name):
    print(f"I have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name}.")
 
# Arguments in wrong order
describe_pet("Buddy", "dog")

Output:

I have a Buddy.
My Buddy's name is dog.

これは Python としては正しいものの、引数が間違った位置に入ってしまうため、意味の通らない出力になります。

キーワード引数

位置に関するエラーを避けるには、関数呼び出し時にパラメータ名を明示する キーワード引数(keyword arguments) を使えます。

python
def describe_pet(animal_type, pet_name):
    print(f"I have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name}.")
 
# Using keyword arguments - order doesn't matter
describe_pet(animal_type="dog", pet_name="Buddy")
print()
describe_pet(pet_name="Whiskers", animal_type="cat")

Output:

I have a dog.
My dog's name is Buddy.
 
I have a cat.
My cat's name is Whiskers.

キーワード引数では、Python は位置ではなく名前で引数をパラメータに対応付けるため、順序は関係ありません。

位置引数とキーワード引数の混在

1回の関数呼び出しで位置引数とキーワード引数を混在させることはできますが、位置引数を先に書く必要があります。

python
def create_profile(username, email, age):
    print(f"Username: {username}")
    print(f"Email: {email}")
    print(f"Age: {age}")
 
# Mixing positional and keyword arguments
create_profile("alice123", email="alice@example.com", age=25)

Output:

Username: alice123
Email: alice@example.com
Age: 25

ただし、キーワード引数の後に位置引数を置くことはできません。

python
# WARNING: This will cause a SyntaxError - for demonstration only
# PROBLEM: Positional argument after keyword argument
# create_profile(username="alice123", "alice@example.com", 25)
# SyntaxError: positional argument follows keyword argument

引数の数は一致させる必要がある

関数を呼び出すときは、正しい数の引数を渡す必要があります(デフォルト値については第20章で扱います)。

python
def add_numbers(a, b):
    result = a + b
    print(f"{a} + {b} = {result}")
 
add_numbers(5, 3)  # 正しい: 2つのパラメータに対して2つの引数

Output:

5 + 3 = 8

引数が少なすぎたり多すぎたりするとエラーになります。

python
# WARNING: These will cause TypeErrors - for demonstration only
 
# PROBLEM: Too few arguments
# add_numbers(5)
# TypeError: add_numbers() missing 1 required positional argument: 'b'
 
# PROBLEM: Too many arguments
# add_numbers(5, 3, 2)
# TypeError: add_numbers() takes 2 positional arguments but 3 were given

式を引数として使う

引数は単純な値である必要はなく、任意の式を使えます。

python
def display_total(price, quantity):
    total = price * quantity
    print(f"Total cost: ${total:.2f}")
 
# Using expressions as arguments
base_price = 10
display_total(base_price * 1.1, 5)  # Price with 10% markup
display_total(15 + 5, 3 * 2)        # Both arguments are expressions

Output:

Total cost: $55.00
Total cost: $120.00

Python はまず各式を評価し、その結果の値を関数に渡します。

関数の中から関数を呼び出す

関数は別の関数を呼び出せます。これにより処理の階層を作れます。これは複雑なタスクを小さく扱いやすい部品に分ける強力なテクニックです。

部屋の面積を計算する例を見てみましょう。

python
def calculate_area(length, width):
    return length * width
 
def display_room_info(room_name, length, width):
    area = calculate_area(length, width)
    print(f"Room: {room_name}")
    print(f"Dimensions: {length} x {width}")
    print(f"Area: {area} square feet")
 
display_room_info("Living Room", 15, 12)

Output:

Room: Living Room
Dimensions: 15 x 12
Area: 180 square feet

: ここでは return を使っていますが、これについては次のセクションで詳しく扱います。いまは、calculate_area() が結果を呼び出し元の関数へ返している、と理解してください。

さらに別の例として、関数同士が積み上がって動く仕組み——温度変換システムを見てみましょう。

python
def celsius_to_fahrenheit(celsius):
    return (celsius * 9/5) + 32
 
def format_temperature(fahrenheit):
    return f"{fahrenheit:.1f}°F"
 
def display_temperature_conversion(celsius):
    fahrenheit = celsius_to_fahrenheit(celsius)
    formatted = format_temperature(fahrenheit)
    print(f"{celsius}°C equals {formatted}")
 
# Use the complete conversion system
display_temperature_conversion(25)
display_temperature_conversion(0)
display_temperature_conversion(100)

Output:

25°C equals 77.0°F
0°C equals 32.0°F
100°C equals 212.0°F

この例では、display_temperature_conversion() が変換のために celsius_to_fahrenheit() を呼び出し、その後、結果を整形するために format_temperature() を呼び出しています。各関数は1つの明確な責務を持つため、コードが理解しやすく保守もしやすくなります。

19.4) return を使って結果を返す

これまでの関数は(表示などの)動作を行ってきましたが、呼び出し元のコードへ値を返してはいませんでした。return 文を使うと、関数が結果を計算し、それを呼び出し元へ返せます。

基本的な return 文

値を計算して返すシンプルな関数はこちらです。

python
def add_numbers(a, b):
    result = a + b
    return result
 
# Capture the returned value
sum_value = add_numbers(5, 3)
print(f"The sum is: {sum_value}")

Output:

The sum is: 8

Python が return 文に遭遇すると、2つのことが起きます。

  1. 関数の実行が即座に停止する(return の後にあるコードは無視されます)
  2. 指定した値が呼び出し元へ返される

値を直接返す

返す前に結果を変数へ保存する必要はありません。式をそのまま返せます。

python
def multiply(a, b):
    return a * b
 
result = multiply(4, 7)
print(f"4 × 7 = {result}")

Output:

4 × 7 = 28

これはより簡潔で、単純な計算では推奨される書き方です。

返された値の利用

関数が値を返すと、その値は他の値と同様にどこででも使えます。

python
def calculate_discount(price, discount_percent):
    discount_amount = price * (discount_percent / 100)
    return discount_amount
 
original_price = 100
discount = calculate_discount(original_price, 20)
 
# Use the returned value in calculations
final_price = original_price - discount
print(f"Original price: ${original_price:.2f}")
print(f"Discount: ${discount:.2f}")
print(f"Final price: ${final_price:.2f}")

Output:

Original price: $100.00
Discount: $20.00
Final price: $80.00

return は関数を即座に終了させる

Python が return 文を実行すると、その時点で関数は即座に停止します。return の後にあるコードは決して実行されません。

python
def check_age(age):
    if age < 18:
        return "Minor"
    # This line only runs if age >= 18
    return "Adult"
 
print(check_age(15))
print(check_age(25))

Output:

Minor
Adult

この振る舞いは、関数内で異なるケースを扱うときに便利です。結果が決まった時点で即座に返せるので、追加の条件をチェックし続ける必要がありません。

return が実行を止めることを示す例はこちらです。

python
def process_number(n):
    if n < 0:
        return "Negative"
    print("This line runs for non-negative numbers")
    if n == 0:
        return "Zero"
    print("This line runs for positive numbers")
    return "Positive"
 
print(process_number(-5))
print()
print(process_number(0))
print()
print(process_number(10))

Output:

Negative
 
This line runs for non-negative numbers
Zero
 
This line runs for non-negative numbers
This line runs for positive numbers
Positive

return がない関数

関数に return 文がない場合、または値を指定しない return がある場合、関数は None を返します。

python
def greet(name):
    print(f"Hello, {name}!")
    # return 文はありません
 
result = greet("Alice")
print(f"The function returned: {result}")

Output:

Hello, Alice!
The function returned: None

同様に、値なしの return(ベア return)も None を返します。

python
def process_data(data):
    if not data:
        return  # 早期終了、None を返す
    print(f"Processing: {data}")
    return "Success"
 
result1 = process_data("")
result2 = process_data("some data")
 
print(f"Result 1: {result1}")
print(f"Result 2: {result2}")

Output:

Processing: some data
Result 1: None
Result 2: Success

複数の値を返す

Python の関数は、カンマで区切って複数の値を返せます。Python はそれらを自動的にタプル(tuple)へまとめます(第15章で学びました)。

python
def calculate_rectangle(length, width):
    area = length * width
    perimeter = 2 * (length + width)
    return area, perimeter
 
# Unpack the returned tuple
rect_area, rect_perimeter = calculate_rectangle(5, 3)
print(f"Area: {rect_area}")
print(f"Perimeter: {rect_perimeter}")

Output:

Area: 15
Perimeter: 16

タプルを1つの値として受け取ることもできます。

python
def get_student_info():
    name = "Alice"
    age = 20
    grade = "A"
    return name, age, grade
 
# Capture as a tuple
student = get_student_info()
print(f"Student info: {student}")
print(f"Name: {student[0]}")

Output:

Student info: ('Alice', 20, 'A')
Name: Alice

異なる型を返す

関数は状況に応じて異なる型の値を返せます。

python
def divide(a, b):
    if b == 0:
        return "Error: Division by zero"
    return a / b
 
result1 = divide(10, 2)
result2 = divide(10, 0)
 
print(f"10 / 2 = {result1}")
print(f"10 / 0 = {result2}")

Output:

10 / 2 = 5.0
10 / 0 = Error: Division by zero

これは動きますが、一般的には別の方法でエラー処理をするのがより良い実践です(例外については Part VII で学びます)。いまは、関数は異なる型を返せるものの、一貫性があるほうが明確なことが多い、と理解してください。

19.5) Docstrings による関数のドキュメント化

プログラムが大きくなり、より多くの関数を作るようになると、各関数が何をするのかをドキュメント化することが非常に重要になります。Python には、docstring(documentation strings) を使って関数をドキュメント化するための組み込みの仕組みがあります。

Docstring とは

docstring とは、関数(またはモジュール、クラス、メソッド)の最初の文として書かれる文字列リテラルです。関数が何をするか、どんなパラメータを受け取り、何を返すかを説明します。docstring は三重引用符(""" または ''')で囲み、複数行にできます。

python
def calculate_area(length, width):
    """Calculate the area of a rectangle.
    
    Takes the length and width of a rectangle and returns the area.
    """
    return length * width

なぜ Docstring が重要なのか

docstring には、いくつかの重要な役割があります。

  1. 自己ドキュメント化(Self-Documentation): 読み手がコードを解析しなくても、関数が何をするかを説明できる
  2. IDE サポート(IDE Support): 多くの開発ツールは、関数を使うときにツールチップとして docstring を表示する
  3. help() 関数(help() Function): Python の組み込み help() 関数は docstring を表示する
  4. プロの実践(Professional Practice): 適切にドキュメント化されたコードは保守・共有がしやすい

基本的な Docstring の形式

シンプルな関数なら、1行の docstring で十分です。

python
def greet(name):
    """Print a personalized greeting."""
    print(f"Hello, {name}!")
 
# Access the docstring
print(greet.__doc__)

Output:

Print a personalized greeting.

docstring は、関数が何をするかを簡潔に説明したものであるべきで、「This function calculates...」のような説明文ではなく、「Calculate...」「Return...」「Print...」のような命令形で書くのがよいとされています。

複数行の Docstring

より複雑な関数には、次の内容を含む複数行の docstring を使います。

  • 1行目に短い要約
  • 空行
  • より詳細な説明
  • パラメータに関する情報
  • 戻り値に関する情報
python
def calculate_discount(price, discount_percent):
    """Calculate the discounted price.
    
    Takes an original price and a discount percentage, then returns
    the amount of discount that should be applied.
    
    Parameters:
    price (float): The original price before discount
    discount_percent (float): The discount percentage (0-100)
    
    Returns:
    float: The discount amount in the same currency as the price
    """
    return price * (discount_percent / 100)
 
# Use help() to see the full docstring
help(calculate_discount)

Output:

Help on function calculate_discount in module __main__:
 
calculate_discount(price, discount_percent)
    Calculate the discounted price.
    
    Takes an original price and a discount percentage, then returns
    the amount of discount that should be applied.
    
    Parameters:
    price (float): The original price before discount
    discount_percent (float): The discount percentage (0-100)
    
    Returns:
    float: The discount amount in the same currency as the price

Docstring の慣習

Python には docstring の書き方に関する慣習が確立されています(PEP 257 に記載)。ここでは重要なガイドラインを紹介します。

1. 三重のダブルクォートを使う: """docstring"""

python
def good_example():
    """This follows the convention."""
    pass
 
def also_valid():
    '''This works but is less common.'''
    pass

2. 1行の docstring は1行に収める:

python
def add(a, b):
    """Return the sum of a and b."""
    return a + b

3. 複数行の docstring は、要約行の後に空行を入れる:

python
def process_order(order_id, items):
    """Process a customer order and update inventory.
    
    This function validates the order, checks inventory availability,
    calculates the total cost, and updates the inventory database.
    
    Parameters:
    order_id (str): Unique identifier for the order
    items (list): List of item dictionaries with 'product' and 'quantity'
    
    Returns:
    dict: Order summary with 'total', 'status', and 'confirmation_number'
    """
    # ここに関数の実装を書きます
    pass

パラメータと戻り値の説明

パラメータと戻り値をドキュメント化するときは、次の点を具体的に書きましょう。

  • パラメータ名: 関数内の実際のパラメータ名と一致させる
  • 型(Types): 期待されるデータ型(型ヒント(type hints)は第43章で学びます)
  • 目的(Purpose): そのパラメータが何のために使われるか
  • 戻り値(Return value): 何を返すか、そしてどの条件で返すか
python
def find_student(student_id, students):
    """Find a student by ID in a list of student records.
    
    Parameters:
    student_id (int): The unique ID number of the student to find
    students (list): List of student dictionaries, each containing 'id' and 'name'
    
    Returns:
    dict: The student dictionary if found, None if not found
    """
    for student in students:
        if student['id'] == student_id:
            return student
    return None

複数の戻り値型を持つ関数の Docstrings

状況に応じて異なる型を返し得る関数では、可能性のあるすべてをドキュメント化します。

python
def safe_divide(a, b):
    """Divide two numbers with error handling.
    
    Parameters:
    a (float): The dividend
    b (float): The divisor
    
    Returns:
    float: The quotient if division is successful
    str: An error message if b is zero
    """
    if b == 0:
        return "Error: Cannot divide by zero"
    return a / b

Docstring へのアクセス

関数の docstring には、次の3つの方法でアクセスできます。

1. __doc__ 属性を使う:

python
def example():
    """This is an example function."""
    pass
 
print(example.__doc__)

Output:

This is an example function.

2. help() 関数を使う:

python
def calculate_bmi(weight, height):
    """Calculate Body Mass Index.
    
    Parameters:
    weight (float): Weight in kilograms
    height (float): Height in meters
    
    Returns:
    float: BMI value
    """
    return weight / (height ** 2)
 
help(calculate_bmi)

Output:

Help on function calculate_bmi in module __main__:
 
calculate_bmi(weight, height)
    Calculate Body Mass Index.
    
    Parameters:
    weight (float): Weight in kilograms
    height (float): Height in meters
    
    Returns:
    float: BMI value

3. 対話的な開発環境(interactive development environments): 多くの IDE やコードエディタは、関数名にマウスを重ねたり入力したりすると、ツールチップとして docstring を表示します。

Docstrings を書くタイミング

docstring は、次のような場合に書くべきです。

  • すべての公開関数(all public functions): プログラムの他の部分や他のプログラマが使うことを想定した関数
  • 複雑な関数(complex functions): 名前とパラメータだけでは目的や振る舞いがすぐにわからない関数
  • 直感的でないパラメータを持つ関数: パラメータ名だけでは、期待する値が十分に伝わらない場合

一方で、次のような場合は docstring を省略することもあります。

  • 非常にシンプルで明白な関数: def add(a, b): return a + b のように、名前とパラメータから目的が明確なもの
  • プライベートな補助関数(private helper functions): 大きな関数の内部でのみ使われる小さな内部関数(ただし、これらも短い docstring があると役立つことがあります)

Docstrings はコメントではない

docstring はコメントとは異なる目的を持つことを忘れないでください。

  • Docstrings: 関数が何をするか、どう使うか(インターフェース)を説明する
  • コメント(Comments): コードが内部でどう動くか(実装)を説明する
python
def calculate_grade(score, total):
    """Calculate the percentage grade from a score.
    
    Parameters:
    score (int): Points earned
    total (int): Total points possible
    
    Returns:
    float: The percentage grade (0-100)
    """
    # ゼロ除算を避ける
    if total == 0:
        return 0.0
    
    # 割合を計算し、小数点以下2桁に丸める
    percentage = (score / total) * 100
    return round(percentage, 2)

docstring は、利用者に対して関数が何をし、どう使うかを伝えます。コメントは、コードを読む人に対して特定の実装上の詳細を説明します。

良いドキュメント作成の習慣を身につける

明確な docstring を書くことは、長期的に大きなメリットがあります。

  • 関数を書くのと同時に docstring も書く: 後回しにせず、目的が頭に新鮮なうちにドキュメント化する
  • docstring を最新に保つ: 関数の振る舞いを変更したら、docstring も更新する
  • 簡潔だが不足のない内容にする: 必要な情報はすべて含めつつ、不要に冗長にしない
  • 必要なら例を使う: 複雑な関数では、docstring に使用例を書くと非常に役立つことがある

良いドキュメントは、コードをよりプロフェッショナルにし、保守しやすくし、他者(そして未来の自分)にとってより価値あるものにします。

© 2025. Primesoft Co., Ltd.
support@primesoft.ai