簡體   English   中英

如何將 function 的許多 arguments 鍵入轉換到位?

[英]How can I type convert many arguments of a function in place?

語境

我使用CherryPy提供一個簡單的網頁,該網頁根據 URL 參數顯示不同的內容。 具體來說,它采用參數的總和並基於此顯示不同的消息。 在 CherryPy 中,網頁可以定義為函數,URL 參數作為參數傳遞給 function。
正如本教程中解釋的URL 參數作為字符串傳遞,因此要計算總和,我想將每個參數轉換為浮點數。 我會有很多URL參數,這么一一做起來好像很麻煩。

如何在原地輸入轉換(大量)arguments?

我試過的

啞的

“愚蠢”的方法是簡單地獲取每個參數並將其重新分配為浮點數:

def dumb(a="0", b="0", c="0", d="0", e="0", f="0", g="0"):
    a = float(a)
    b = float(b)
    c = float(c)
    d = float(d)
    e = float(e)
    f = float(f)
    g = float(g)

    return print(sum([a, b, c, d, e, f, g]))

它是可讀的,但相當重復並且不是很“pythonic”。

循環locals()

我發現的另一個選擇是將本地變量重新分配給字典,然后循環遍歷它並從字典中調用值。

def looping_dict(a="0", b="0", c="0", d="0", e="0", f="0", g="0"):
    args = locals()
    for key in args:
        if key in ["a", "b", "c", "d", "e", "f", "g"]:
            args[key] = float(args[key])

    return print(sum([args["a"], args["b"], args["c"], args["d"], args["e"], args["f"], args["g"]] ) )

這有點煩人,因為我每次都必須參考字典。 所以一個簡單的引用d變成了args["d"] 也無助於代碼的可讀性。

這是我以前用於類似的東西的@convert裝飾器(最初受https://stackoverflow.com/a/28268292/4597523啟發):

import functools, inspect

def convert(*to_convert, to):
    def actual_convert(fn):
        arg_names = inspect.signature(fn).parameters.keys()
        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            args_converted = [to(arg) if arg_name in to_convert else arg
                               for arg, arg_name in zip(args, arg_names)]
            kwargs_converted = {kw_name: to(val) if kw_name in to_convert else val
                                 for kw_name, val in kwargs.items()}
            return fn(*args_converted, **kwargs_converted)
        return wrapper
    return actual_convert

@convert('a', 'c', 'd', to=str)
def f(a, b, c=5, *, d, e=0):
    return a, b, c, d, e

print(f(1, 2, d=7))

# Output: ('1', 2, 5, '7', 0)
# Passed params `a` and `d` got changed to `str`,
# however `c` used the default value without conversion

它使用inspect.signature來獲取非關鍵字參數名稱。 我不確定 CherryPy 如何傳遞參數或如何獲取名稱,但這可能是一個可靠的開始。 使用functools.wraps很重要——它確保保留原始簽名 function 簽名,這對於 CherryPy 似乎很重要。

這僅記錄在更改日志中,但自 2016 年以來cherrypy >= 6.2.0有一個@cherrypy.tools.params工具完全符合您的要求(前提是您使用支持類型注釋的 Python 3 版本):

import cherrypy


@cherrypy.tools.params()
def your_http_handler(
        a: float = 0, b: float = 0,
        c: float = 0, d: float = 0,
        e: float = 0, f: float = 0,
        g: float = 0,
):
    return str(a + b + c + d + e + f + g)

添加它的 PR 是PR #1442——你可以通過查看那里的測試來探索它的用法。

如果您的 Python 由於某種原因已經過時,您可以這樣做:

import cherrypy


def your_http_handler(**kwargs):
    # Validate that the right query args are present in the HTTP request:
    if kwargs.keys() ^ {'a', 'b', 'c', 'd', 'e', 'f', 'g'}:
        raise cherrypy.HTTPError(400, message='Got invalid args!')

    numbers = (float(num) for num in kwargs.values())  # generator expression won't raise conversion errors here
    try:
        return str(sum(numbers))  # this will actually call those `float()` conversions so we need to catch a `ValueError`
    except ValueError as val_err:
        raise cherrypy.HTTPError(
            400,
            message='All args should be valid numbers: {exc!s}'.format(exc=val_err),
        )

PS 在您最初的帖子中,您使用return print(...)這是錯誤的。 print()總是返回None ,因此您會將"None"發送回 HTTP 客戶端,而print(arg)的參數只會在您運行服務器的終端中打印出來。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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