[英]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.