Half Width Katakana の判定

def isNotHalfWidthKana(field_data, all_data):
    test = unicode(field_data, 'utf-8')
    KANA = range(65377, 65439)
   
    if len([c for c in test if ord(c) in KANA]) > 0:
        raise validators.ValidationError(_('Not Half-width Kana.'))
def isNotIncludeHalfWidthKana(field_data, all_data):
    test = unicode(field_data, 'utf-8')
    han_kana = re.compile(u'[\uFF61-\uFF9F]+')   
    
    if han_kana.search(test) is not None:
        raise validators.ValidationError(_('Not Half-width Kana.'))

相変わらず、他人の話題に乗っかってばかりな訳ですが、自分ならこう書くかな。

_KANA = set(range(0xFF61, 0xFFA0))
def isNotIncludeHalfWidthKatakana(field_data, all_data):
    for c in (ord(c) for c in field_data.decode('utf-8')):
        if c in _KANA:
            raise validators.ValidationError(_('Not Half-width Kana.'))

list より set のがいいよね?パフォーマンス気にしすぎ?とりあえず Unicode 的には Half Width Katakana なのと isNot だと紛らわしいので、isNotIncludeHalfWidthKatakana に。
それはともかくとして range が終端を含まないのを忘れていると U+FF9F が通過してしまうオチが。境界値試験重要。まぁ、正規表現でもいいんだけど "+" はなくてもいいんじゃね。
あとこんなのもありか。Functional Programming スキーな人向け。

def empty(iterable):
    for i in iterable:
        return false
    return true

_KANA = set(range(0xFF61, 0xFFA0))
def isNotHalfWidthKatakana(field_data, all_data):
    test = field_data.decode('utf-8')
    if not empty(c for c in test if ord(c) in _KANA):
        raise validators.ValidationError(_('Not Half-width Kana.'))

追記

ord を忘れていたので、追加。thanks id:perezvon さん。
しかし、ぼけてるなぁ。

再追記

そもそも、正規表現エンジンがやっていることそのものを、Pythonのコードにしているわけだから、速いわけがない。

正規表現エンジンはCで書かれているんだから Python で工夫するより正規表現使ったほうが早いよ、という話。うん、まあそりゃそうだ。でも以前書いたように

sum(itertools.repeat(1, 1000000))

とかが思いのほか早かったりするので、用意されている builtin function*1正規表現エンジン、あるいは psyco の有無とかでまたちょっと違う結果が出たりすることもあるかも。場合によっては pytst なんかのほうが適しているということも。IronPython とかだとどうかな。
でも Java だと正規表現エンジン自体も Pure Java だったりしてさてどうしたものか、というオチがあったりもする。

*1:なんで any とか all が builtin にないんだ?