Edited at

Pythonの文字列の比較演算子について

More than 1 year has passed since last update.

最近、Pythonでデータ処理を行い、簡単なアラート機能のバッチ処理を行うコードをレビューしています。

その中で、次のようなコードがあってびっくりしました。(若干書き換えてます)

import pandas as pd

def select_this_month(df: pd.DataFrame) -> pd.DataFrame:
"""今月のデータのみを取り出す
Args:
df: フィルタリング対象のデータフレーム
Returns:
フィルターしたデータフレーム
"""

now = df["Date"].max()
y, m = now[0:4], now[5:7]
res = df[df['Date'] >= (y + "-" + m + "-01")]
return res

このコードを見た際、pandasのmaxで最大値を取り出しているし(数値型やdatetime型?)、スライスで部分文字列を取り出している(文字列型?)し、「なんだコレ?pandas組み込みの日付型?」と思ってしまいました。

よくよく調べると、これはただの文字列型で、それに比較演算子(不等号)が定義されているだけでした。

a = '2016-12-31'

b = '2016-01-01'
a > b
# => True
a < b
# => False

Pythonの公式ドキュメントにも、比較演算子の結果を明示している箇所を見つけました


Strings (instances of str) compare lexicographically using the numerical Unicode code points (the result of the built-in function ord()) of their characters.

Strings and binary sequences cannot be directly compared.


とりあえずGoogle翻訳しておきます。


文字列(strのインスタンス)は、文字のUnicodeコードポイント(組込み関数ord()の結果)を使って辞書的に比較します。 [3]

ストリングとバイナリシーケンスを直接比較することはできません。


ord関数のドキュメントにもこう書いてあるのでUnicodeポイントで比較されるみたいですね。


1 文字の Unicode 文字を表す文字列に対し、その文字の Unicode コードポイントを表す整数を返します。例えば、 ord('a') は整数 97 を返し、 ord('€') (ユーロ記号) は 8364 を返します。これは chr() の逆です。


ということで、


  • 日付の文字列が必ず0詰めされている

  • YYYY-MM-DDの形式で計算されている

なら文字列型でも問題なく挙動しそうです。

やっぱり日付型を使ったほうがいいとは思いますが。