簡體   English   中英

Python 輸入有效性和使用斷言

[英]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以及初始設定nargconv

實際的驗證發生在 funcDecorated 內部,它...

  • 接受輸入參數列表,
  • 通過驗證和/或轉換它來替換第 n 個參數(無論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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM