Python:向方法调用添加可选参数的更优雅的方式
Python: More elegant way to add optional parameters to method call
这可能看起来微不足道,但这是我 运行 经常遇到的情况,并且希望找到一种更优雅的方式来编写此代码。该方法虽然与问题不太相关,但采用文本值和可选的 is_checked 值来创建单选按钮(使用 dominate)。在这种情况下,我无法将 'checked' 设置为 None 或 false - 它必须存在或不存在。不过,我似乎不必将 'input' 行写两次,只是为了有选择地添加一个参数。
def _get_radio_button(text: str, is_checked=False):
with label(text, cls="radio-inline") as lbl:
if is_checked:
input(text, type="radio", name="optradio", checked='checked')
else:
input(text, type="radio", name="optradio")
return lbl
这将是我的第二种方法,但它是相同的代码行并且可读性较差 - 尽管可能有点干。
a = dict(type='radio', name='optradio')
if is_checked:
a['checked']='checked'
with label(text, cls="radio-inline") as lbl:
input(text, **a)
问题:如何在不牺牲可读性的情况下用尽可能少的行来处理这个代码案例?
您的代码看起来不错,除了 a
的命名明显不同,它可能是 input_opts
或类似的东西。
另一种让它更清晰的可能性是对常见的东西使用直接关键字参数,并使用 **
注入可选的参数。当只有一个是可选的时,这可以很短,例如:
checked_arg = {'checked': 'checked'} if is_checked else {}
with label(text, cls="radio-inline") as lbl:
input(text, type="radio", name="optradio", **checked_arg)
仅作为概念:)您可以用这种方式装饰自己的或外来的(库)函数。更重要的是,您可以将装饰器设置为 class(使用 __call__
方法装饰底层函数),可以使用简单的 "morphisms" 底层函数参数(它们可能是函数列表 -作为装饰器 class 构造函数的参数)。你也可以制作更多声明式风格的装饰器并检查底层函数参数(例如默认值)——你只受限于自己的幻想:)所以:
from functools import wraps
def adapt_gui_args(callable):
@wraps(callable)
def w(*args, **kwargs):
if kwargs.pop('is_checked', False): kwargs['checked'] = 'checked'
return callable(*args, **kwargs)
return w
# may be decorated with adapt_gui_args if it's your function
def input(*args, **kwargs):
print("args: ", args)
print("kwargs: ", kwargs)
# decorate input function outside its source body
input = adapt_gui_args(input)
def test(is_checked=False):
input(1, 2, type="radio", is_checked=is_checked)
test(False)
test(True)
这可能看起来微不足道,但这是我 运行 经常遇到的情况,并且希望找到一种更优雅的方式来编写此代码。该方法虽然与问题不太相关,但采用文本值和可选的 is_checked 值来创建单选按钮(使用 dominate)。在这种情况下,我无法将 'checked' 设置为 None 或 false - 它必须存在或不存在。不过,我似乎不必将 'input' 行写两次,只是为了有选择地添加一个参数。
def _get_radio_button(text: str, is_checked=False):
with label(text, cls="radio-inline") as lbl:
if is_checked:
input(text, type="radio", name="optradio", checked='checked')
else:
input(text, type="radio", name="optradio")
return lbl
这将是我的第二种方法,但它是相同的代码行并且可读性较差 - 尽管可能有点干。
a = dict(type='radio', name='optradio')
if is_checked:
a['checked']='checked'
with label(text, cls="radio-inline") as lbl:
input(text, **a)
问题:如何在不牺牲可读性的情况下用尽可能少的行来处理这个代码案例?
您的代码看起来不错,除了 a
的命名明显不同,它可能是 input_opts
或类似的东西。
另一种让它更清晰的可能性是对常见的东西使用直接关键字参数,并使用 **
注入可选的参数。当只有一个是可选的时,这可以很短,例如:
checked_arg = {'checked': 'checked'} if is_checked else {}
with label(text, cls="radio-inline") as lbl:
input(text, type="radio", name="optradio", **checked_arg)
仅作为概念:)您可以用这种方式装饰自己的或外来的(库)函数。更重要的是,您可以将装饰器设置为 class(使用 __call__
方法装饰底层函数),可以使用简单的 "morphisms" 底层函数参数(它们可能是函数列表 -作为装饰器 class 构造函数的参数)。你也可以制作更多声明式风格的装饰器并检查底层函数参数(例如默认值)——你只受限于自己的幻想:)所以:
from functools import wraps
def adapt_gui_args(callable):
@wraps(callable)
def w(*args, **kwargs):
if kwargs.pop('is_checked', False): kwargs['checked'] = 'checked'
return callable(*args, **kwargs)
return w
# may be decorated with adapt_gui_args if it's your function
def input(*args, **kwargs):
print("args: ", args)
print("kwargs: ", kwargs)
# decorate input function outside its source body
input = adapt_gui_args(input)
def test(is_checked=False):
input(1, 2, type="radio", is_checked=is_checked)
test(False)
test(True)