Python WebAcademy Blog

Pythonのmax()・min()・sum()とは?key引数で最大値の基準を変える方法と、空リストでエラーになる落とし穴を初心者向けに解説

|

リストの中でいちばん大きい値や合計を求めるとき、forループで変数を更新していませんか。Pythonの組み込み関数max()・min()・sum()を使えば、こうした集計を1行で書けます。基本の使い方から、key引数で比べる基準を変える方法、空のリストでValueErrorになる落とし穴とdefault引数での対策、小数の合計で起きる誤差まで、手元で動かした結果とともに初心者向けに解説します。

テストの点数のリストから、最高点と合計点を出したい。プログラミングを学びはじめると、こうした集計の課題にすぐ出会いますよね。

最初のうちは、forループを回して、今までの最大値より大きければ変数を書き換える、という書き方をしがちです。それでも正しく動きますが、Pythonには同じことを1行でこなせる道具が最初から用意されています。

それが、組み込み関数のmax()・min()・sum()です。どれもimportなしで使えて、最大値・最小値・合計をすぐに求められます。

今回は、この3つの関数の基本から、比べる基準を変えるkey引数、空のリストを渡したときのエラー、小数の合計で起きる誤差まで紹介します。サンプルの実行結果は、手元のPython 3.11で確かめたものです。

max()・min()・sum()は何をする関数か

まずは、3つの関数の役割をひとことで整理しておきましょう。名前は英語のmaximum、minimum、sumから来ていて、意味そのままの動きをします。

3つの関数の違いを、表にまとめてみました。

関数 返すもの 空のリストを渡すと よく使う追加の引数
max() いちばん大きい要素 ValueErrorになる key、default
min() いちばん小さい要素 ValueErrorになる key、default
sum() 要素をすべて足した値 0を返す start

表の真ん中の列は、あとで詳しく説明する大事なポイントです。同じ集計の仲間なのに、空のときの動きがmax()・min()とsum()で分かれています。

どの関数も、リストだけでなくタプルや集合、ジェネレータ式など、順番に要素を取り出せるものなら何でも受け取れます。こうした値のことを、Pythonではイテラブルと呼びます。

基本の使い方をコードで確かめよう

まずは、いちばんシンプルな使い方から見ていきましょう。ループで書いた場合と比べると、短くなるのがよくわかります。

scores = [72, 85, 64, 91, 58]

# ループで最大値を探す書き方
highest = scores[0]
for score in scores:
    if score > highest:
        highest = score
print(highest)  # 91

# 組み込み関数を使う書き方
print(max(scores))  # 91
print(min(scores))  # 58
print(sum(scores))  # 370

# 平均点も1行で出せる
print(sum(scores) / len(scores))  # 74.0

ループ版では、最初の値を仮の最大値として置き、ひとつずつ比べて更新していました。max()を使えば、その手順をまるごと任せられます。

平均値は、sum()で出した合計をlen()で求めた個数で割るだけです。集計の基本は、この組み合わせでほとんどまかなえます。

引数を直接並べる書き方

max()とmin()は、リストを渡すだけでなく、値をカンマで直接並べることもできます。max(3, 8, 5)と書けば、8が返ってきます。

2つの値のうち大きいほうを選びたいときに便利です。たとえば、計算結果がマイナスにならないよう、max(0, balance)のように下限をつける書き方は実務でもよく使います。

ただし、sum()にはこの書き方がありません。sum(1, 2, 3)と書くとTypeErrorになるので、足したい値は必ずリストなどにまとめて渡しましょう。

文字列を比べるとどうなるか

max()とmin()は、数値だけでなく文字列にも使えます。文字列の場合は、辞書の並びのように先頭の文字から順に比べられます。

ここで少し注意したいのが、大文字と小文字の扱いです。Pythonでは文字に割り当てられた番号で比べるため、大文字のほうが小文字より小さいものとして扱われます。

そのため、min(['apple', 'Banana', 'cherry'])はBananaを返します。人間の感覚とはずれることがあるので、次に紹介するkey引数で比べ方をそろえるのがおすすめです。

key引数で比べる基準を変える

max()とmin()のいちばんの便利ポイントが、key引数です。keyに関数を渡すと、要素そのものではなく、その関数を通した結果で大小を比べてくれます。

文字列の長さで比べたり、辞書の特定の値で比べたりと、使える場面はたくさんあります。具体的なコードで見てみましょう。

words = ['apple', 'Banana', 'kiwi']

# 文字数がいちばん多い単語
print(max(words, key=len))  # Banana

# 大文字小文字を区別せずに比べる
print(min(words, key=str.lower))  # apple

students = [
    {'name': '佐藤', 'score': 78},
    {'name': '鈴木', 'score': 92},
    {'name': '高橋', 'score': 85},
]

# 点数がいちばん高い生徒の辞書をまるごと取り出す
top = max(students, key=lambda s: s['score'])
print(top['name'])  # 鈴木

ポイントは、keyで比べたあとに返ってくるのが、関数を通した値ではなく元の要素そのものだということです。最後の例では、点数の92ではなく、鈴木さんの辞書がまるごと返ってきます。

この性質のおかげで、いちばん点数の高い生徒の名前を知りたい、といった要望に1行で応えられます。lambdaの書き方に自信がない方は、次の記事もあわせて読んでみてください。

【関連記事】Pythonのlambda(ラムダ式)とは?

key引数の考え方は、並べ替えのsorted()とまったく同じです。sorted()の使い方を押さえておくと、max()とmin()のkeyも自然に読めるようになります。

【関連記事】Pythonのsorted()の使い方

辞書でいちばん大きい値のキーを探す

辞書をそのままmax()に渡すと、比べられるのは値ではなくキーです。{'a': 3, 'b': 5}を渡すと、キーの中で大きい'b'が返ってきます。

値がいちばん大きいキーを知りたいときは、keyに辞書のgetメソッドを渡すのが定番です。max(sales, key=sales.get)と書けば、売上がいちばん多い商品名を取り出せます。

辞書の扱いに慣れていない方は、こちらの記事で基本をおさらいしておくと安心です。

【関連記事】Pythonの辞書(dict)の使い方

同じ最大値が複数あるとき

最大値の要素が2つ以上あるとき、max()はどれを返すのでしょうか。答えは、先に出てきたほうです。

たとえば、同じ点数の生徒が2人いたら、リストの前にいる生徒が返されます。min()も同じで、最小値が並んだときは最初に見つかった要素が選ばれます。

空のリストでValueErrorになる落とし穴

ここからが、今回いちばん伝えたいポイントです。max()とmin()に空のリストを渡すと、ValueErrorというエラーで処理が止まります。

最大値を決める候補がひとつもないので、答えようがないというわけです。手元のPython 3.11では、max() arg is an empty sequenceというメッセージが表示されました。

私は10年ほどエンジニアとして開発に関わってきましたが、このエラーで夜間のバッチ処理を止めてしまったことがあります。テスト中は毎回データが入っていたのに、本番でたまたま対象が0件の日があり、そこでmax()が落ちてしまいました。

厄介なのは、データが入っているあいだは何の問題もなく動いてしまう点です。データが空になりうる場面では、空のときにどうするかを先に決めておくのが大切です。

default引数で空のときの値を決める

この落とし穴への対策として用意されているのが、default引数です。空のイテラブルを渡したときは、エラーにせずにdefaultの値を返してくれます。

書き方は、max(scores, default=0)のようにキーワード引数で渡すだけです。データがあるときはふつうに最大値を返し、空のときだけ0を返します。

デフォルト値には、Noneを指定することもできます。max(scores, default=None)としておけば、あとからif文で値がないケースを分けて扱えます。

なお、default引数が使えるのは、リストなどをひとつだけ渡したときに限られます。max(5, 3, default=0)のように値を直接並べた書き方と組み合わせると、TypeErrorになるので注意しましょう。

sum()の使い方と注意点

続いて、合計を求めるsum()を見ていきます。こちらは空のリストを渡しても、エラーにならずに0を返してくれます。

足し算の世界では、何も足さない状態が0だと考えるとイメージしやすいでしょう。そのため、max()やmin()のようなdefault引数は用意されていません。

start引数で初期値を足す

sum()には、start引数という2つ目の引数があります。これは、合計の出発点になる値です。

sum([1, 2, 3], start=10)と書くと、10に1、2、3を足した16が返ってきます。前月までの累計に今月の値を足し込むような場面で役に立ちます。

また、TrueとFalseは計算のうえでは1と0として扱われます。そのため、sum([True, False, True])は2になり、条件に合う件数を数える書き方としてもよく使われます。

文字列はsum()で連結できない

足し算という意味では、文字列も+でつなげられますよね。ところが、sum()で文字列を連結しようとするとTypeErrorになります。

エラーメッセージには、代わりに''.join(seq)を使うよう案内が表示されます。文字列をつなげたいときは、sum()ではなくjoin()を使いましょう。

小数の合計で起きる誤差

sum()でもうひとつ知っておきたいのが、小数を足したときの誤差です。0.1を10回足したら1.0になりそうですが、手元のPython 3.11では0.9999999999999999と表示されました。

これはsum()の不具合ではなく、コンピュータが小数を2進数で扱うために起きる誤差です。0.1のような値は、2進数ではぴったり表せないのが原因です。

誤差の仕組みについては、こちらの記事で詳しく解説しています。

【関連記事】Pythonの小数の計算誤差はなぜ起きる?

誤差を小さくしたいときは、標準ライブラリのmathモジュールにあるmath.fsum()が使えます。同じ0.1を10個並べたリストでも、math.fsum()なら1.0が返ってきました。

ちなみに、Python 3.12ではsum()が小数を足すときの計算方法が改良され、多くの環境で精度が上がっています。そのため、同じコードでもPythonのバージョンによって結果がわずかに変わることがあります。

方法 0.1を10個足した結果(Python 3.11) 向いている場面
sum() 0.9999999999999999 ふだんの集計
math.fsum() 1.0 小数の誤差を抑えたいとき

お金の計算のように、1円の誤差も許されない場面ではdecimalモジュールを使うのが安心です。用途に合わせて道具を選びましょう。

実務で使うときのコツ

最後に、実務でmax()・min()・sum()を使うときのコツを2つ紹介します。どちらも、私が現場で何度も見てきたポイントです。

1つ目は、ジェネレータ式と組み合わせることです。sum(item['price'] for item in cart)のように書けば、いったんリストを作らずに合計を出せます。

角かっこで囲んだリスト内包表記でも動きますが、データが大きいときはジェネレータ式のほうがメモリにやさしくなります。この書き方は、any()やall()でも同じように使えます。

【関連記事】Pythonのany()とall()とは?

2つ目は、比べる値の型をそろえることです。数値と文字列が混ざったリストをmax()に渡すと、比べられずにTypeErrorになります。

CSVや画面の入力から読み込んだ値は、数字に見えても文字列のことがよくあります。集計する前に、int()やfloat()で数値に変換しておくと安全です。

まとめ

max()・min()・sum()は、最大値・最小値・合計を1行で求められる組み込み関数です。ループで変数を更新するよりも短く、何をしたいコードなのかがひと目で伝わります。

key引数を使えば、文字数や辞書の値など、好きな基準で比べられます。返ってくるのは元の要素そのものなので、いちばん点数の高い生徒をまるごと取り出す、といった使い方も簡単です。

そして、空のリストを渡すとmax()とmin()はエラーになることだけは覚えておいてください。データが空になりうる場面では、default引数を付ける習慣が、私のような夜間の呼び出しを防いでくれます。

まずは、手元のコードにある最大値探しのループを、1か所だけmax()に書き換えてみてはいかがでしょうか。

ここまでお読みいただきありがとうございました。

参考情報

次のアクション

記事で学んだ内容を実際に動かしてみよう

Python WebAcademyでは、ブラウザ上でコードを書きながら基礎から実践まで体系的に学べます。

Python WebAcademyの学習画面

あわせて読む

関連記事

ブログ一覧へ

Python学習ロードマップ

まずはこの3講座から

記事で気になったテーマを、順番に手を動かしながら学べます。

ロードマップを見る