【发布时间】:2020-11-03 10:46:03
【问题描述】:
问题:
我想写一个通用函数:
def foo(positional, a=None, b=None, c=None, *, keyword_only=True):
# ... ?? ... magic_code
return a_b_c_in_tuple_in_order
返回一个保留关键字参数顺序的元组a,b,c:
xx = 'some object'
>>> foo(xx, 1, 2, 3)
(1, 2, 3)
>>> foo(xx, 1, 2)
(1, 2)
>>> foo(xx, a=1, b=2, c=3, keyword_only=False)
(1, 2, 3)
>>> foo(xx, b=2, a=1, c=3) # <---- key behaviour
(2, 1, 3)
>>> foo(xx, b=2, c=3)
(2, 3)
>>> foo(xx, c=3, a=1)
(3, 1)
>>> foo(xx, a='may be anything', c=range(5), b=[1, 2])
('may be anything', range(0, 5), [1, 2])
>>> foo(xx, b=1)
(1,) # may be 1 or (1,)
我怎样才能做到这一点?这样的代码是非pythonic吗,如果是,我应该改用什么?
主要目标是易于使用和可读性。
为什么?
我的目标是使用这样的函数进行单位系统之间的转换(例如 SI 英制,但实际用例更高级),用户可以直观地编写例如
l, (t1, t2) = convert(params, lengths=L, times=(T1, T2), normalized=True)
# or
(t1, t2), l = convert(params, times=(T1, T2), lengths=L, normalized=True)
无论函数是如何定义的,以及数量是浮点数、数组等。
角落案例:
不需要对此类误用做出良好反应,但万无一失是一个好处:
>>> foo(b=2, a=1, c=3, positional=xx)
(2, 1, 3)
>>> foo(b=2, positional=xx, a=1, keyword_only=False, c=3)
(2, 1, 3)
【问题讨论】:
-
用户如何使用这些元组?返回这些值的字典更加pythonic,因为关键字/命名参数没有排序。它们可以按任何顺序传递。更 Pythonic 的返回是:
{"a":1,"b":2,"c":3},然后用户选择如何处理存储在每个键中的值。为什么订单对这里的用户很重要? -
@spacether 用法将在 Why?* 部分中描述。我希望返回值是不可打包的,因此整个转换都在一个易于阅读的行内完成。
-
for conversions有点模糊。拥有元组后如何处理它们?你不需要知道值对应的参数名称吗? -
@spacether 哦,对不起,你是对的。我的意思是不同公制单位之间的转换(例如 SI - 英制,但实际用例更复杂)。
-
实际上,如果您正在寻找单位转换,astropy 有一个非常强大和健壮的实现,它是described here,源代码是here。在我看来,这比依赖关键字参数的顺序要好得多,因此它可能对您有用。
标签: python python-3.x arguments parameter-passing