2016-05-03 10 views
1

pythonで無効な入力を明示的にチェックする方法を最良に(そしてどの程度まで)実装するべきかアドバイスが必要です。強力なタイプ設定を持つC++のバックグラウンドから来ていますが、これはいつも私のために混乱しています。Pythonで無効な型をチェックする

def m(start:float, up:float, down:float): 
    pass 

今すぐ他の2つは、私が何かを行うことができます0より大きくなければなりませんしながら、0以上でなければならない起動:

ので、議論のために私たちは、以下のメソッドシグネチャを持っていると仮定しましょう以下のような:

def m(start:float, up:float=1, down:float=1): 
    if start <= 0.0: 
     raise ValueError("Error") 
    if up< 0.0: 
     raise ValueError("Error") 
    if down< 0.0: 
     raise ValueError("Error") 

私はこれがある限り、入力型がfloatまたはfloat型に匹敵するいくつかの数値型であるとして罰金になります推測しています。しかし、Pythonでは、関数を呼び出すのを止めるものは何もありません。

m(start=[], up="Hello", down={}) 

これらの比較は意味がありません。この状況に対処するための無限の方法は何ですか?

+2

呼び出し元が契約に違反しているため、スクリプトがうまくいかないようにします。 –

+2

Pythonの入力が一般的になっています:) https://docs.python.org/3/library/typing.html Pythonの新しいrelで新しく変更されています。 3.4,3.5,3.5.1 ... あなたは何ですか? –

+1

Pythonは 'TypeError'を送出します。あなたのユーザーが開発者の場合は、最後にドキュメントを読むでしょう。そうでない場合は、コードのどこかに横たわっている恐ろしいバグがあります。それはあなたのせいではありません。 – gboffi

答えて

0

引数が浮動小数点であることを確認するには、type()を使用します。例えば
if type(start) != float
それとも、そのようなisinstance()機能を使用することができます。

if not isinstance(start, float): 
    raise TypeError 
0

いくつかの方法で、最も一般的なものはおそらくありますEAFPは(簡単に許可よりもforgivness聞いて):

def m(start:float, up:float=1, down:float=1): 
    try: 
     if start <= 0.0: 
      raise ValueError 
     if up < 0.0: 
      raise ValueError 
     if down < 0.0: 
      raise ValueError 
    except TypeError: 
     # This is just to give a more meaningful error message. 
     raise TypeError('Arguments must be numbers.') 

これはPython 2では黙って失敗するでしょうが、python 3では、not-numberとnumberを比較するとTypeErrorが発生します。その意味では、彼は彼が何か間違ったことをしたことを彼に知らせるでしょう。より多くのニシキヘビがあるtry ... except ...でEAFPを考える(私を含め)

from numbers import Real # or Number if you want to allow compley-types too 

def m(start, up=1, down=1): 
    # Compare if each argument is a real (floating point) number: 
    if not isinstance(start, Real) or not isinstance(up, Real) or not isinstance(down, Real) : 
     raise TypeError("Arguments must be numbers.") 
    ... 

ほとんどの人:

他のオプションも防御的プログラミングとして知られている型チェックとLBYLの概念(あなたが跳躍する前に見て)ですisinstance -checksの方が快適だと思われる場合は、代わりの方法があります。

0

あなたの質問に答えて:m(start=[], up="Hello", down={})は、if start <= 0.0:を試みるとすぐにプログラムをクラッシュさせます(例外を発生させます)。 m('3', '4', '55.27')の文字列の場合は、がfloatに変換されるため、状況がより問題になる可能性があります。

浮動小数点でも数値でもない到着が、呼び出しコードの論理エラーを示す状況で防御したい場合は、実行時にテストすることができます。 assertステートメントは、不適切に捕捉される可能性の低いAssertionErrorを発生させます。だから、:

assert type(start)==float, "start is not a float" 
assert type(up) ==float or type(up) ==int 
assert type(down)==float or type(down)==int 

これらはまた、彼らは後日コメントアウトするのは非常に簡単であるという利点を持っている、と彼らはすぐにdef声明に従うならば、多少他の言語での宣言のように(コメントかどうか)をお読みください。

またアサートを使用して値を確認することができます。

assert start >= 0 
assert up > 0 and down > 0 

またはこれらの値がエラーであるので、多分それはValueErrorを調達する方が良いでしょう:

if start < 0 or up <= 0 or down <= 0: 
    raise ValueError("Bad arguments start={} up={} down={}".format(start,up,down)) 

主な違いは、ValueErrorを上げることを意図しているということです信号が発呼者によって感知される可能性があることを示す一方、assertは、論理エラーが検出され、即時のプログラム終了がおそらく最良であることを示すことを意図している。 (あるいは、対話的なコマンドパーサーの一番上にあるキャッチオールハンドラに伝播してください)。

関連する問題