2011-01-19 12 views
1

私の質問には具体的な答えがあるとは思いますが、とにかくわかりません。私は多くのパラメータを持つ関数を書いていますが、それぞれがNoneのいずれかであるか、値の範囲が限られています。私は良い入力を与えるためにユーザーを信頼しないので、私はそのタイプのために各パラメータをチェックする必要があり、それが正しいタイプ(またはNone)であれば、それが正しい範囲にあるかどうかを見たいと思います。このよう Pythonの論理引数チェック

# size 
if isinstance(size, str): 
    if size in range(4): 
     self.data[uid]['size'] = int(size) 
    else: 
     warnings.warn("ID %s: illegal size %s" % (uid, size)) 
     self.data[uid]['size'] = None 
elif size == None:         
    self.data[uid]['size'] = None 
else: 
    warnings.warn("ID %s: illegal size %s" % (uid, str(size))) 
    self.data[uid]['size'] = None 

などが繰り返しになってきている

、これを自動化する例外/警告を投げると、コードの冗長性を削減するライブラリがあるかもしれない場合、私は思っていた:これは平均が私はこのようなコードの多くを持っています。

おかげ

+6

'それぞれのパラメータをチェックする必要があります。あなたが間違っているように聞こえます。予想されるタイプとして使用し、失敗をキャッチするだけです。 – Falmarri

+3

私は入力を確認しなければならないと思っていました。私がそれをやめると、プログラミングはずっと簡単になりました。ちょうど良いと仮定し、エラーを処理します。これは、Pythonのイディオム「Permissionよりも許してもらうのが簡単です」と関係しています。 – Wilduck

+2

'=='の代わりに 'size is None'を使います(' == 'は' .__ eq __() 'を呼び出すため' 'なし 'と比較すると正しく動作するかもしれません)。 –

答えて

1

、これを自動化 投げる例外/警告と コードの冗長性を低減するであろう ライブラリがあるかもしれません場合、私は思っていました。

私はこのようなもののためにformencodeを使用します。これはHTMLフォームを解析するためのみたいですが、それを渡したものを幸せに解析して検証します。すべての入力を一度に検証するスキーマクラスを定義します。

0

プロジェクトがライブラリであり、あなたの「ユーザー」は、他の開発者である場合は、すべてでこれをしません。せいぜい、アサーションを使用してテストを置き換える:ユーザーが不正な入力を提供する場合、彼らはすぐにそれについて聞く

assert 0 <= int(size) <= 4, "size must be between 0 and 4" 

この方法では、 - それは右のそれを得るために彼らの責任になります。


あなたのプロジェクトはアプリケーションであり、あなたの「ユーザが」私の祖母である場合は、あなたがあなた自身の検証を行う必要がありますアウトクラッシュが許容応答ではありません。しかし、この場合、可能な入力についてもっと知っておく必要があります(たとえば、テキストボックスから入力されたものなので、文字列にすることができます)。

私の提案は、上記のようにあなたのユーティリティー関数をコード化し、別々に検証(つまり、UIレイヤー)を実行することです。ユーティリティ/ライブラリ関数は、値を検証して(警告しても)オーバーライドすることは非常にまれです。呼び出し元/ユーザーが何かのことを正しく行うまで、呼び出し元/ユーザーがそれ以上になるのを防ぐ必要があります。

1

私は上記に同意します:sizeが正しいタイプであると仮定し、そうでない場合は例外を発生させます(またはエラーが返されます)。

例外を発生させる可能性のある入力を扱うときには便利なパターンがあります。つまり、入力によって発生した例外をラップして入力を含むようにします。あなたが得られますので、たとえば、:raiseの三番目の引数は、元のトレースバックを使用しますのでスタックトレースはにあなたを指します

try: 
    parse(input) 
catch Exception, e: 
    raise ParseError("while parsing %r: %r" %(input, e)), None, sys.exc_info()[2] 

 
ParseError: while parsing 'number = foo': ValueError: invalid literal for int() with base 10: 'foo' 

をコードは次のようになります(size = int(value)など)を呼び出すのではなく、実際にエラーの原因となった行を確認してください。

1

私はこれを書き換えるになります。このような

# size 
if isinstance(size, str): 
    if size in range(4): 
     self.data[uid]['size'] = int(size) 
    else: 
     warnings.warn("ID %s: illegal size %s" % (uid, size)) 
     self.data[uid]['size'] = None 
elif size == None:         
    self.data[uid]['size'] = None 
else: 
    warnings.warn("ID %s: illegal size %s" % (uid, str(size))) 
    self.data[uid]['size'] = None 

if size in ["0", "1", "2", "3"]: # alternative: if size in map(str, range(4)): 
    self.data[uid]['size'] = int(size) 
else: 
    if size != None: 
     warnings.warn("ID %s: illegal size %s" % (uid, size)) 
    self.data[uid]['size'] = None  

私が心から好きではないことはisinstance(size, str)(明示的な型チェックの使用は一般的に簡単にそれ以来、Pythonでひんしゅくを買うされています休憩ducktyping)。

これは、Pythonで型チェックを自動化するためのライブラリを簡単に見つけることができないためです。これは、言語のコアインテントに反します。

+0

-1:不一致:サイズ== "foo"またはサイズ== "123.45"でサイズが "-666"の場合に警告を出し、サイズ== 1.23(浮動小数点数)の場合は警告を受け取りません。 –

+0

@John Machin:真、固定(OPの想定される要件のため) – ChristopheD

関連する問題