概要(*args は「いくつでも受け取れる位置引数」をまとめる仕組み)
*args は、関数が受け取る「位置引数」を任意の個数まとめて受け取るための記法です。関数内ではタプルとして扱われ、合計・連結・ループなどを柔軟に書けます。固定個数に縛られないため、API をシンプルに保ちつつ拡張性を確保できます。
def add_all(*args):
return sum(args)
print(add_all(1, 2, 3)) # 6
print(add_all(10)) # 10
print(add_all()) # 0
Python基本構文と動作(ここが重要)
受け取り側のルール(タプルとして届く)
args は「位置引数の束」をタプルで受け取ります。名前は慣習的に args が多いですが、numbers など任意で構いません。
def show(*items):
print(items, type(items)) # (1, 'a', True) <class 'tuple'>
show(1, "a", True)
Python固定引数と *args の並び
固定の引数がある場合は先頭に置き、*args をその後ろに置きます。これで「必須+任意数」の使い勝手が良くなります。
def power_all(exp, *xs):
return [x ** exp for x in xs]
print(power_all(2, 2, 3, 4)) # [4, 9, 16]
Python*args と **kwargs の同時利用
任意個の位置引数(args)と、任意個のキーワード引数(*kwargs)は併用できます。順序は「固定 → *args → キーワード固定 → **kwargs」。
def render(label, *classes, id=None, **attrs):
cls = " ".join(classes)
rest = " ".join(f'{k}="{v}"' for k, v in attrs.items())
return f'<button id="{id}" class="{cls}" {rest}>{label}</button>'
print(render("OK", "primary", "rounded", id="ok", disabled=True))
Python渡す側のテクニック(アンパック・前処理・フォワーディング)
既存のシーケンスをそのまま渡す(アンパック)
引数リストがすでに配列・タプルなら、呼び出し側で * を付けて展開できます。既存データの再利用に便利です。
def connect(host, port, secure=False):
return (host, port, secure)
args = ("example.com", 443)
opts = {"secure": True}
print(connect(*args, **opts)) # ('example.com', 443, True)
Pythonラッパ関数で「受けて整形して渡す」
*args を受けて、バリデーションや変換をしてから別関数へ渡す“フォワーディング”が定番です。
def safe_sum(*nums):
cleaned = [int(n) for n in nums if str(n).isdigit()]
return sum(cleaned)
print(safe_sum("10", "x", "25")) # 35
Python設計の勘所(柔軟性と可読性のバランスを深掘り)
*args を使うべき場面・避ける場面
- 「引数の数が本質的に不定」なら使う(合計、連結、複数対象への同一操作)。
- 「意味の異なるパラメータが複数」なら、キーワード引数で名前を付けるほうが読みやすい。*args で混在させると可読性が落ちます。
# 良い例:意味が同じ“数値の集合”
def multiply_all(factor, *nums):
return [factor * n for n in nums]
Pythonバリデーションとエラーメッセージ
*args は型・個数が自由なので、関数の先頭で必要条件をチェックし、明確なエラーメッセージを返すと利用者が迷いません。
def mean(*nums):
if not nums:
raise ValueError("少なくとも1つは数値を渡してください")
if not all(isinstance(n, (int, float)) for n in nums):
raise TypeError("数値のみ受け付けます")
return sum(nums) / len(nums)
Pythonパフォーマンスの意識(大量引数・コピー)
*args はタプル化されます。極端に大量の引数を毎回渡す設計は避け、必要ならイテラブル一つを受け取る形(関数内で反復)に切り替えるとメモリ負荷を抑えられます。
# 大量データなら“イテラブル1つ”のインターフェースも候補
def sum_iter(nums):
return sum(nums)
Python実務での使いどころ(集約・レンダリング・ロギング)
集約処理(合計・最大・整形)
def join_csv(*cells):
return ",".join(map(str, cells))
print(join_csv("A", 10, True)) # A,10,True
PythonUI/HTML のクラス合成やタグ属性の拡張
def classes(*names):
return " ".join(n for n in names if n)
print(classes("btn", "primary", None, "rounded")) # btn primary rounded
Pythonログ出力のメッセージパーツ結合
def log(*parts, level="INFO"):
msg = " ".join(map(str, parts))
print(f"[{level}] {msg}")
log("start", 200, "OK") # [INFO] start 200 OK
log("retry", 3, level="WARN") # [WARN] retry 3
Python応用パターン(位置限定・キーワード限定・型ヒント)
位置限定(/)+ args + キーワード限定()
API を壊さないために、インターフェースを明示します。/ の左は「位置のみ」、* の右は「キーワードのみ」。
def scale_all(factor, /, *nums, rounding=None):
vals = [n * factor for n in nums]
return [round(v, rounding) if rounding is not None else v for v in vals]
print(scale_all(0.5, 10, 20, 30, rounding=1)) # [5.0, 10.0, 15.0]
Python型ヒントで意図を伝える
*args の型は「タプルの要素型」として書けます。IDE 補完や静的解析が効きやすくなります。
def concat_all(*parts: str, sep: str = "") -> str:
return sep.join(parts)
Python組み合わせの安全運用
*args で受けたものをそのまま別関数に渡す際は、必要な検証や変換を挟みます。責務が明確になり、バグの原因が局所化されます。
例題で身につける(定番から一歩先まで)
例題1:複数ファイル名から拡張子を統一付与
def add_ext(*names, ext=".txt"):
return [n if n.endswith(ext) else n + ext for n in names]
print(add_ext("a", "b.txt", "c")) # ['a.txt', 'b.txt', 'c.txt']
Python例題2:複数数列の“同じ処理”をまとめて適用
def sum_each(*series):
return [sum(xs) for xs in series]
print(sum_each([1,2], (3,4,5), [10])) # [3, 12, 10]
Python例題3:引数の前処理+委譲(フォワード)
def normalize(*texts):
def norm(s): return s.strip().lower()
return [norm(s) for s in texts if s and s.strip()]
print(normalize(" Apple ", "", "TEA")) # ['apple', 'tea']
Python例題4:ラップして安全に合計(非数値は捨てる)
def sum_safe(*values):
nums = []
for v in values:
try:
nums.append(float(v))
except (TypeError, ValueError):
pass
return sum(nums)
print(sum_safe("10", "x", 2.5)) # 12.5
Pythonまとめ
args は「位置引数をいくつでも受ける」ための強力でシンプルな仕組み。受け取りはタプル、固定引数の後ろに置く、*kwargs と併用する場合の順序を守る。渡す側は * アンパックで既存データを展開し、受け取り側ではバリデーションと変換を早めに行う。大量引数ではイテラブル1つのインターフェースも検討し、/ と * を使って API を堅牢にする。これを押さえれば、初心者でも安全で拡張性の高い関数設計ができるようになります。
