islower() と isupper() の関数ですがリファレンスをざっと確認したり、他の言語の経験のある方は英文字の小文字、大文字を判定する関数だと認識がある人も多いのではないかと思います(自分もそうでした)。
しかし、注意してください。ほぼその認識で大丈夫なのですが一部の場面ではワナが発動します。
※正確には正しい挙動を理解していないのが問題なのかもしれませんが他言語やってた多くの人がこの落とし穴にまりますって orz。ドキュメントに注記入れといてー。
実例を紹介します。 islower() は主に以下のような場合に使用するかと思います。
# -*- coding: utf-8 -*- if "abcABC".islower(): print u"すべて小文字です" else: print u"すべて小文字ではありません"
こちらには大文字の ABC が存在するためもちろん判定は False となり「すべて小文字ではありません」と表示されます。
同様に以下のパターンの場合の判定結果にはみなさん納得できるかと思います。
文字列 | 判定結果 |
---|---|
abcABC | False |
a | True |
A | False |
1 | False |
文字列なし("")のとき | False |
空白(" ")のとき | False |
しかし、以下の判定結果はPythonに不慣れな方は違和感を感じるのではないでしょうか。
文字列 | 判定結果 |
---|---|
a1 | True |
aA1 | False |
a1b2c3 | True |
a b(途中に空白) | True |
a/b | True |
1 を判定したときはもちろん False となるのですが a1 と英文字の小文字と混在した文字列の場合は True となるのです。
同様に isupper() もこちらの動作は納得できるかと思います。
文字列 | 判定結果 |
---|---|
A | True |
a | False |
文字列なし("")のとき | False |
空白(" ")のとき | False |
しかし、こちらの判定には違和感を感じる方もいるのでは
文字列 | 判定結果 |
---|---|
A1 | True |
aA1 | False |
A1B2C3 | True |
A B(途中に空白) | True |
A/B | True |
islower() 関数のときと同様に A1 という場合は True を返すのです。
なおこちらの仕様ですがはじめはWindows版のPythonのバグの可能性はないのかと思い、他の環境でもテストしてみましたが同様の結果でした。こちらの判定で正しい仕様のようです。
ちなみに確認した環境とPythonのバージョン情報は以下となります。
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32
FreeBSD(さくらインターネットの環境)
Python 2.4.5 (#2, May 22 2008, 13:38:36) [GCC 3.4.4 [FreeBSD] 20050518] on freebsd6
Python 2.5.2 (r252:60911, Feb 22 2008, 07:57:53) [GCC 4.0.1 (Apple Computer, Inc. build 5363)] on darwin
まとめ
islower()
判定 | 条件 | |
---|---|---|
True | 小文字のみの文字列 | |
True | 小文字+大文字小文字の区別の無い文字の文字列 | |
False | 大文字小文字の区別の無い文字のみの文字列 | |
False | 大文字が含まれる文字列 |
isupper()
判定 | 条件 | ||
---|---|---|---|
True | 大文字のみの文字列 | ||
True | 大文字+大文字小文字の区別の無い文字の文字列 | ||
False | 大文字小文字の区別の無い文字のみの文字列 | ||
False | 小文字が含まれる文字列 |
他言語と同様の判定を行いたい場合は以下の様に処理する必要があります。
# -*- coding: utf-8 -*- flag = True s = "abc1def" for i in s: if not i.islower(): flag = False break if flag: print "'" + s + u"'は小文字のみの文字列です" else: print "'" + s + u"'は小文字のみの文字列ではありません"
2008/06/24追記:
id:c-yanさんのコメントによりもっと短いコードで処理できることが判明したので短いバージョンのサンプルを追加します(c-yanさんありがとうございます)。
# -*- coding: utf-8 -*- s = "abc1def" if all(i.islower() for i in s): print "'" + s + u"'は小文字のみの文字列です" else: print "'" + s + u"'は小文字のみの文字列ではありません"
ちなみに help(all) すると以下の様に出力されます。
Help on built-in function all in module __builtin__: all(...) all(iterable) -> bool Return True if bool(x) is True for all values x in the iterable.
ヘルプの内容を確認すると
イテレータの全てのデータ(今回の場合は i.islower() )が True の場合のみ、Trueを返し、それ以外は False を返すようです。