[英]Python input validity and using asserts
我正在嘗試對我的 python 代碼執行良好的輸入有效性檢查,但我也希望它簡潔。 也就是說,我不想采用的解決方案是:
def some_func(int_arg, str_arg, other_arg):
try:
int_arg = int(int_arg)
except TypeError, ValueError
logging.error("int_arg must respond to int()")
raise TypeError
try:
if str_arg is not None:
str_arg = str(str_arg)
except TypeError
logging.error("Okay, I'm pretty sure this isn't possible, bad example")
raise TypeError
if other_arg not in (VALUE1, VALUE2, VALUE3):
logging.error("other arg must be VALUE1, VALUE2, or VALUE3")
raise TypeError
這只是太多的代碼和太多的空間來只檢查 3 個參數。
我目前的做法是這樣的:
def some_func(int_arg, str_arg, other_arg):
try:
int_arg = int(int_arg) #int_arg must be an integer
str_arg is None or str_arg = str(str_arg) #str_arg is optional, but must be a string if provided
assert other_arg in (VALUE1, VALUE2, VALUE3)
catch TypeError, ValueError, AssertionError:
logging.error("Bad arguments given to some_func")
throw TypeError
我失去了我的日志消息的特異性,但在我看來,這更簡潔,老實說更具可讀性。
我特別想知道的一件事是 assert 語句的使用。 我讀過不鼓勵使用斷言作為檢查輸入有效性的方式,但我想知道這是否是使用它的合法方式。
如果沒有,是否有類似的方法來執行此檢查(或一般進行此驗證)仍然非常簡潔?
你可以發明一個裝飾器來為你驗證參數。
這是語法的樣子:
@validate(0, int)
@validate(1, str, logMessage='second argument must respond to str()')
@validate(2, customValidationFunction)
def some_func(int_arg, str_arg, other_arg):
# the control gets here only after args are validated correctly
return int_arg * str_arg
這是驗證裝飾器工廠的簡單實現。
def validate(narg, conv, logMessage = None):
def decorate(func):
def funcDecorated(*args):
newArgs = list(args)
try:
newArgs[narg] = conv(newArgs[narg])
except Exception, e:
# wrong argument! do some logging here and re-raise
raise Exception("Invalid argument #{}: {}".format(narg, e))
else:
return func(*newArgs)
return funcDecorated
return decorate
是的,這里有一些函數嵌套,但這一切都是有道理的。 讓我解釋:
validate(narg, converter)
成為一個函數,它接受一些設置並返回一個特定的裝飾器 ( decorate
),它根據這些設置進行操作decorate
然后被用於裝飾給定功能( func
通過創建一個新的功能需要一些位置參數) funcDecorated
,是以相同的參數func
( *args
)並且被寫入輸入功能方面func
以及初始設定narg
, conv
。實際的驗證發生在 funcDecorated 內部,它...
conv
做什么),func
。 為了對多個參數執行此操作,我們使用不同的參數多次應用validate
。 (可以將其重寫為僅裝飾一次,但這樣 IMO 看起來更清晰。)
看到它在行動: http : //ideone.com/vjgIS
請注意, conv
可以作為...
請注意,此實現不處理關鍵字參數。
使用斷言非常適合檢查參數有效性(類型、類或值,這正是您要檢查的內容)。
你說:
我特別想知道的一件事是 assert 語句的使用。
所以我認為這個頁面對你有用。
特別是這部分:
斷言不應用於測試由於錯誤的用戶輸入或操作系統/環境故障(例如未找到文件)而可能發生的故障情況。
更新:看看mypy: https ://mypy.readthedocs.io/en/stable/
def some_func(int_arg: int, str_arg: str, other_arg):
@Vicent提供了一個很棒頁面的鏈接(可能在此期間已被編輯)。 如果您需要檢查,建議按如下方式進行類型檢查
from types import IntType, StringType
def some_func(int_arg, str_arg, other_arg):
assert type(int_arg) == IntType, "id is not an integer: %r" % int_arg
assert type(str_arg) == StringType or not str_arg
assert other_arg in (VALUE1, VALUE2, VALUE3), "other arg must be VALUE1, VALUE2, or VALUE3"
斷言的好處是它顯示了失敗的代碼行。
您可以查看合同庫。 它允許您聲明對函數參數(甚至其返回值)的約束。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.