Pythonの基礎知識(基礎編)

【Pythonの基礎知識】引数と戻り値で“情報のやりとり”を自動化する

プログラムは、ただ命令を並べただけでは動きがぎこちないものです。

人と同じで「何を渡され、何を返すか」が決まっていないと、意思疎通ができません。

Pythonの関数も同じで、引数が“言葉”のように情報を渡し、戻り値が“返事”として結果を伝えます。

この仕組みを理解すると、コードがまるで会話のように動き始め、無駄のない自動化が見えてきます。

Pythonの基礎知識(基礎編)


🟣 Pythonの基礎知識(基礎編)
📌基本文法から実用テクニックまで、Pythonの土台を固めるステップアップ講座
└─ 【Pythonの基礎知識(基礎編)】仕組みから学ぶ思考と自動化のプログラミング講座
  ├─ STEP 0:Pythonを動かす“仕組み”を理解する
  | ├─【Pythonの基礎知識】Pythonを動かす環境とは何か? “自分専用の環境”を作る
  | ├─【Pythonの基礎知識】Hello Worldの裏側にある実行の仕組み
  | └─【Pythonの基礎知識】Pythonのファイル構造と実行パスを理解する
  |
  ├─STEP 1:Pythonで“考える仕組み”を作る(思考編)
  | ├─【Pythonの基礎知識】データ型で世界を定義する|数・文字・真偽の正体
  | ├─【Pythonの基礎知識】変数と値の動きを通して仕組みを理解しよう
  | ├─【Pythonの基礎知識】条件分岐で“判断を任せる”仕組みを作る
  | ├─【Pythonの基礎知識】for文で“人の手”を離す仕組みを作る
  | └─【Pythonの基礎知識】while文で“継続する仕組み”を作る
  |
  ├─STEP 2:Pythonで“情報を扱う仕組み”を作る(構造編)
  | ├─【Pythonの基礎知識】コレクション型の正しい選び方(list, tuple, dict, set)
  | ├─【Pythonの基礎知識】リストで情報を整理し、仕組みに流れを持たせる
  | ├─【Pythonの基礎知識】辞書型でデータを“意味”で管理する
  | └─【Pythonの基礎知識】集合型で重複を排除し、無駄をなくす仕組みを作る
  |
  ├─STEP 3:Pythonで“動きを再利用する仕組み”を作る(関数・モジュール編)
  | ├─【Pythonの基礎知識】関数で処理を再利用する|“人間の手順”を仕組みに変える
  | ├─【Pythonの基礎知識】引数と戻り値で“情報のやりとり”を自動化する
  | ├─【Pythonの基礎知識】モジュールとパッケージで“仕組みを部品化”する
  | └─【Pythonの基礎知識】importの裏側を理解し、コードを分離する設計思考
  |
  ├─STEP 4:Pythonで“データを扱う仕組み”を作る(入出力・永続化編)
  | ├─【Pythonの基礎知識】ファイル操作でデータを読み書きする仕組みを作る
  | ├─【Pythonの基礎知識】CSVを自在に扱う仕組みを作る
  | ├─【Pythonの基礎知識】JSONで構造化データを操る
  | └─【Pythonの基礎知識】例外処理で“壊れない仕組み”を設計する
  |
  └─STEP 5:Pythonで“自動化する仕組み”を作る(応用実践編)
    ├─【Pythonの基礎知識】スクリプトを自動実行させる仕組みを作る
    ├─【Pythonの基礎知識】日次タスクを自動化して人の時間を解放する
    ├─【Pythonの基礎知識】外部APIを活用して作業を外部化する
    └─【Pythonの基礎知識】ログを記録して仕組みの信頼性を高める

引数で“何を”処理に渡すか明確にする

関数を使う目的は「同じ処理を何度も書かないため」ですが、引数を使いこなせていないと結局同じようなコードを量産することになります。

引数は、関数に“何を処理してほしいか”を伝える仕組みです。

ここを丁寧に設計できるかどうかで、コードの再利用性と可読性が大きく変わります。

同じ処理をまとめたのに、毎回中身を書き換える必要があるのはなぜ?
それは関数に「具体的な情報(引数)」を渡していないからです。

例えば、足し算を行う関数を作っても、数値を引数として渡さなければ常に同じ結果しか得られません。

def add(a, b):
    return a + b

result = add(5, 7)
print(result)

【出力例:】

12

このように、引数を通して関数に「何をしたいか」を渡すことで、関数が汎用的な“仕組み”に変わります。

これは、人が「具体的な依頼」を伝えないと正確に動けないのと同じです。

じゃあ、引数を増やせばどんな処理にも対応できるってこと?
いいえ、むやみに増やすと逆に管理が難しくなります。重要なのは、必要最低限で目的を達成する設計です。

ここからは、引数がない場合にどのような問題が生じるのかを整理します。

引数なしではどこがボトルネックになるか

引数を使わずに関数を設計すると、柔軟性が失われてしまいます。

たとえば、計算式の中に具体的な値を直接書き込むと、値を変更するたびに関数を修正しなければなりません。

def calc_discount():
    price = 1000
    discount = price * 0.1
    return price - discount

print(calc_discount())

【出力例:】

900.0

この関数は一見正しく動作しますが、価格を変更するたびに関数の中身を編集する必要があります。

つまり、関数が“固定化”されてしまい、メンテナンスコストが上がるのです。

確かに、数値を変えるたびにコードを開くのは面倒ですね。
そうです。引数を導入することで、この問題は一瞬で解決できます。

def calc_discount(price):
    discount = price * 0.1
    return price - discount

print(calc_discount(2000))

【出力例:】

1800.0

引数を導入することで、関数の内部を変更せずに外部から情報を渡せるようになります。

これは、システム開発全体でも「外部設定化」という重要な設計思想につながります。

引数を設計する際のポイント

引数を設計するうえで大切なのは、「使う人が迷わないこと」と「将来の変更に強い構造」を作ることです。

まず、引数名は必ず意味の通る単語にします。

例えば x, y のような一時的な名前ではなく、price, discount_rate のように“何を渡しているのか”が明確に伝わる名前を付けます。

引数の順番が多くなると、どれが何か分からなくなりますね。
その場合は「キーワード引数」を使うのがおすすめです。

def calc_discount(price, rate):
    return price - (price * rate)

print(calc_discount(price=3000, rate=0.2))

【出力例:】

2400.0

キーワード引数を使えば、引数の順番に左右されず、意図を明確に伝えられます。

これはチーム開発でも非常に効果的で、「この値は何を意味しているのか」をコードから読み取れるようになります。

最後に、引数を設計する際は「必須」と「任意」を明確に分けることです。

デフォルト値を設定しておくと、呼び出し側が省略できる場面が増えます。

def calc_discount(price, rate=0.1):
    return price - (price * rate)

print(calc_discount(1500))
print(calc_discount(1500, 0.3))

【出力例:】

1350.0
1050.0

このように、デフォルト値を活用することで「使いやすくて壊れにくい関数」を設計できます。

引数の数や型、呼び方を少し工夫するだけで、コードはぐっと読みやすく、再利用もしやすくなります。

なるほど、関数の設計ってただ動かすだけじゃなく、“人に優しくする工夫”なんですね。
まさにその通りです。引数は技術ではなく、思いやりの設計です。

戻り値で“どう”出力を返すか設計する

関数は入力を受け取って処理を行いますが、最も重要なのは“結果をどう返すか”です。

戻り値の設計を誤ると、正しい計算をしても活かせない関数になってしまいます。

戻り値は、関数から外の世界に情報を渡す唯一の出口です。

ここをきちんと意識して設計することで、コードが再利用しやすく、意図が明確な仕組みに変わります。

戻り値って、書かなくても勝手に返ってくるんじゃないの?
実は“返ってくる”ものと“返している”ものは違います。そこを理解すると関数設計の精度が一気に上がります。

明示的な戻り値と暗黙のNoneの違い

Pythonでは、関数の末尾で returnを使わない場合、自動的に Noneが返されます。

この挙動を知らないと、思わぬバグの原因になることがあります。

def greet():
    print("Hello!")

result = greet()
print(result)

【出力例:】

Hello!
None

この例では、print()でメッセージは表示されますが、greet()の結果として返ってくるのはNoneです。

つまり「表示」と「返す」はまったく別の動作です。

printしてるのに、なんでNoneになるんですか?
print()は“出力する”だけで、“戻す”わけではないからです。

次のようにreturnを使うと、関数の外で結果を使い回せるようになります。

def greet():
    return "Hello!"

result = greet()
print(result)

【出力例:】

Hello!

このように、明示的にreturnを使うことで、処理結果を別の関数に渡したり、条件分岐に利用したりできます。

Noneを返す関数は単発で動くスクリプトには向いていますが、再利用性が求められるプログラムでは“出口の明確化”が欠かせません。

どんな関数でもreturnを書いておくべきなんですか?
いいえ。明確な結果を外部で使うときだけreturnを使えば十分です。

戻り値を明示的にすることは、プログラムの意図を明確にする「自己説明的コード」にもつながります。

複数値・タプル・辞書で返す場面と使い分け

Pythonの戻り値は1つだけに限られません。

タプルや辞書を使えば、複数の値をまとめて返すことができます。

これにより、関数の設計をシンプルに保ちながら、柔軟な情報伝達が可能になります。

def calc_stats(numbers):
    total = sum(numbers)
    avg = total / len(numbers)
    return total, avg

result = calc_stats([10, 20, 30])
print(result)

【出力例:】

(60, 20.0)

このように、return total, avgと書くと、自動的にタプルとして返されます。

呼び出し側でアンパックすれば、変数に直接代入もできます。

total, avg = calc_stats([5, 10, 15])
print(total)
print(avg)

【出力例:】

30
10.0

タプル以外にも使える方法ってありますか?
もちろんです。辞書を使えば、より意味のあるデータ構造で返すことができます。

def calc_stats_dict(numbers):
    total = sum(numbers)
    avg = total / len(numbers)
    return {"total": total, "average": avg}

print(calc_stats_dict([2, 4, 6]))

【出力例:】

{'total': 12, 'average': 4.0}

辞書を使えば、キーで意味を付けて返せるため、後から見ても「何の値か」がすぐに理解できます。

一方で、タプルは軽量かつ高速なので、単純な構造を返す場合に向いています。

以下の表に、それぞれの使いどころをまとめます。

形式特徴向いている場面
単一値最もシンプル処理結果が1つだけのとき
タプル軽量で順序あり2〜3個の関連データを返すとき
辞書意味が明確で可読性高い複数の属性を含むデータを返すとき

戻り値の設計は、プログラムの読みやすさと保守性に直結します。

複雑な関数ほど、どんな情報を“どの形で”返すかを整理することで、後のトラブルを防げます。

なるほど、戻り値ってただ返すだけじゃなく、コードの未来も左右するんですね。
その通りです。戻り値の設計は、関数の「出口戦略」です。

引数・戻り値で情報のやりとりを自動化する設計パターン

関数の本質は「動きをひとまとめにして使い回すこと」です。しかし、ただまとめるだけでは本当の自動化にはなりません。

引数と戻り値を組み合わせて情報をやり取りすることで、関数が“人間の手を離れて動く仕組み”になります。

ここでは、実際の開発現場で得た経験をもとに、設計のコツと注意点を整理します。

同じような処理を毎回書き換えるのって、本当に無駄ですよね。
そうですね。だからこそ、情報を引数と戻り値で渡せるようにすれば、関数は一気に賢くなります。

実体験:繰り返し処理を関数化して可読性・再利用性を高めたケース

以前、CSVデータを分析するツールを作っていたとき、最初は同じ処理を何度もコピーして書いていました。

たとえば、行ごとに合計を出す、平均を出す、結果を出力する――似たような処理ばかりで、少し変更するたびに全ての箇所を直す必要がありました。

ちょっと計算方法を変えたいだけなのに、全部修正するのは大変ですね。
まさにその問題でした。だから、処理の共通部分を関数にして、データを引数で渡す形に変えたんです。

def calc_average(data):
    total = sum(data)
    avg = total / len(data)
    return avg

numbers = [10, 20, 30, 40]
print(calc_average(numbers))

【出力例:】

25.0

このように関数化すると、処理の流れが一目でわかり、他のデータにも使い回せます。

さらに、戻り値を利用することで関数の外で再利用が可能になり、組み合わせ次第で新しい機能にも発展させられます。

結果をprintするだけじゃなく、別の処理にも渡せるようになるんですね。
そうです。戻り値を使うことで、関数がまるで部品のように連携できるようになります。

たとえば、平均値を求めたあとに「しきい値を超えたデータを抽出する」関数と組み合わせることもできます。

def filter_high(data, threshold):
    return [x for x in data if x > threshold]

avg = calc_average([10, 20, 30, 40])
print(filter_high([10, 20, 30, 40], avg))

【出力例:】

[30, 40]

こうして“関数をつなげる”構成にすると、同じデータ処理でも構造が整理され、修正時の影響範囲も最小限になります。

これが自動化の第一歩です。

注意すべき落とし穴と気づき

引数と戻り値を組み合わせれば自動化は容易になりますが、いくつかの落とし穴があります。

特に注意したいのは「戻り値の扱い方」と「関数の責任範囲」です。

戻り値の扱い方って、どういう意味ですか?
一つの関数で“全部返そう”とすると、返り値が複雑になりすぎて扱いにくくなるんです。

たとえば、計算結果もエラーメッセージも全部ひとまとめに返す関数を作ると、受け取る側が混乱します。

def calc(data):
    if not data:
        return "Error: empty data"
    return sum(data)

【出力例:】

Error: empty data

なるほど、戻り値の型が一定じゃないと後で扱いづらいですね。
その通りです。戻り値の型は常に一定にしておくことが大切です。

このようなケースでは、辞書やタプルを使って結果と状態を分けて返すのが有効です。

def calc(data):
    if not data:
        return {"status": "error", "result": None}
    return {"status": "ok", "result": sum(data)}

print(calc([]))
print(calc([1, 2, 3]))

【出力例:】

{'status': 'error', 'result': None}
{'status': 'ok', 'result': 6}

このように戻り値の構造を統一しておくと、呼び出し側は状態を確認して安全に処理を続けられます。

また、関数の責任範囲を広げすぎると、関数が“何をしているのか”が見えにくくなります。

処理は「入力を受け取る」「計算する」「出力する」という単位で分け、1つの関数が1つの目的を果たすように設計します。

つまり、関数にやらせすぎないことも大事なんですね。
そうです。引数と戻り値の設計は、コードを“分かりやすく保つための会話”なんです。

こうした設計パターンを積み重ねることで、関数同士が連携し、まるで自動的に意思疎通しているようなコード構造が完成します。

それこそが“情報のやりとりを自動化する”という考え方です。

型ヒント・ドキュメンテーションで“意図”を明示する

コードは正しく動いても、「なぜそう書かれているのか」が伝わらないと、他人にも過去の自分にも理解されません。

特に関数では、引数と戻り値の“意味”があいまいなままだと、誤った使われ方をしてしまいます。

Pythonでは「型ヒント」と「ドキュメンテーション(docstring)」を使うことで、関数の意図を明確に伝えることができます。

これは、単なる説明ではなく“未来の自分や他人へのメッセージ”です。

動くからいいや、って思ってコメントを省くことが多いです。
動くことよりも、読み手に伝わることのほうが大切です。型ヒントとdocstringは、その橋渡しになります。

型ヒント(アノテーション)で引数・戻り値の意図を伝える

型ヒント(Type Hint)は、関数が「どんな型のデータを受け取り、どんな型を返すか」を明示する仕組みです。

コードの実行には影響しませんが、読みやすさと信頼性を大きく高めます。

特に大規模開発では、静的解析ツールやIDE(VSCodeなど)が型情報を補完してくれるため、バグを未然に防げます。

def calc_total(price: int, tax: float) -> float:
    return price + (price * tax)

result = calc_total(1000, 0.1)
print(result)

【出力例:】

1100.0

この例では、priceが整数、taxが小数であること、そして戻り値が小数型(float)で返ることが明示されています。

もし誤って文字列を渡した場合、IDEが警告を出すため、実行前にミスを発見できます。

型ヒントってPythonらしくない気もします。もっと自由に書けるのが魅力ですよね。
確かにPythonは柔軟ですが、“自由=野放し”ではありません。型ヒントはその自由を保ちながら安全性を確保する方法です。

また、Python 3.9以降ではリストや辞書にも簡潔な型指定ができるようになりました。

def join_names(names: list[str]) -> str:
    return ", ".join(names)

print(join_names(["Alice", "Bob", "Carol"]))

【出力例:】

Alice, Bob, Carol

このように、型ヒントを付けることで関数の意図が明確になり、他の人が関数を呼び出す際に迷わなくなります。

“何を渡し、何が返るか”が一目でわかるコードは、まるでドキュメントそのものです。

docstring/コメントで情報のやりとり仕様を補足する

型ヒントで「型」は伝わっても、「どう使うか」までは伝わりません。 その“使い方の意図”を伝えるのが、docstring(ドックストリング)です。関数の直下に三重引用符で記述し、関数の目的・引数・戻り値を簡潔に書くのが基本です。

def calc_discount(price: int, rate: float = 0.1) -> float:
    """
    Calculate discounted price.
    
    Args:
        price (int): original price
        rate (float): discount rate (default: 0.1)
    
    Returns:
        float: discounted price
    """
    return price - (price * rate)

このように書いておくと、help()関数で関数の仕様を即座に確認できます。

help(calc_discount)

【出力例:】

Help on function calc_discount in module __main__:

calc_discount(price: int, rate: float = 0.1) -> float
    Calculate discounted price.
    
    Args:
        price (int): original price
        rate (float): discount rate (default: 0.1)
    
    Returns:
        float: discounted price

確かにhelp()で見られるのは便利ですね。でも、コメントとどう違うんですか?
コメントは“開発者向けのメモ”、docstringは“関数仕様書”です。つまり、他人がコードを読むときに最初に見るのがdocstringです。

また、docstringはSphinxなどの自動ドキュメント生成ツールでも活用されます。

関数を追加するたびに仕様書を自動更新できるため、メンテナンスコストも大幅に減ります。

方法目的メリット
型ヒント引数・戻り値の型を明示IDE補完・エラー検知
docstring関数の仕様を文書化自動ドキュメント生成が可能
コメント実装上の補足・意図コード修正時の理解を補助
型ヒントとdocstringって、どちらか一方だけで十分じゃないんですか?
いいえ、目的が違います。型ヒントは“形式を守る”、docstringは“意図を伝える”。この2つが揃って初めて、強いコードになります。

型ヒントとドキュメンテーションを組み合わせれば、コードそのものが「生きた説明書」になります。

それは、未来の自分が迷わず作業を進められるための、最も確実な投資です。

まとめ

関数は「処理をまとめるもの」ではなく、「情報を受け取り、結果を返す仕組み」です。

引数で“何を渡すか”、戻り値で“どう返すか”を意識するだけで、コードは人が理解できる構造に変わります。

そして、型ヒントやドキュメンテーションを使えば、その意図を未来の自分や他人にも伝えられます。

結局、関数って人と会話してるようなものなんですね。
そうです。引数と戻り値はその言葉、型ヒントとdocstringはその通訳です。コードは“人が理解できる仕組み”にしてこそ生きます。

コードを速く書くことよりも、“正しく伝わる設計”を意識することが、最終的に最も効率的なプログラミングになります。

次のおすすめ記事

よく読まれている記事

1

「私たちが日々利用しているスマートフォンやインターネット、そしてスーパーコンピュータやクラウドサービス――これらの多くがLinuxの力で動いていることをご存じですか? 無料で使えるだけでなく、高い柔軟 ...

2

Linux環境でよく目にする「Vim」という名前。サーバーにログインしたら突然Vimが開いてしまい、「どうやって入力するの?」「保存や終了ができない!」と困った経験をした人も多いのではないでしょうか。 ...

3

ネットワーク技術は現代のITインフラにおいて不可欠な要素となっています。しかし、ネットワークを深く理解するためには、その基本となる「プロトコル」と「レイヤ」の概念をしっかり把握することが重要です。 こ ...

4

この記事は、Linuxについて勉強している初心者の方向けに「Shellスクリプト」について解説します。最後まで読んで頂けましたら、Shellスクリプトはどのような役割を担っているのか?を理解出来るよう ...

5

Javaは世界中で広く使われているプログラミング言語であり、特に業務システムやWebアプリケーションの開発において欠かせない存在です。本記事では、初心者向けにJavaの基礎知識を網羅し、環境構築から基 ...

-Pythonの基礎知識(基礎編)