函数参数中裸星号的目的是啥? [复制]

Posted

技术标签:

【中文标题】函数参数中裸星号的目的是啥? [复制]【英文标题】:What is the purpose of a bare asterisk in function arguments? [duplicate]函数参数中裸星号的目的是什么? [复制] 【发布时间】:2014-05-27 03:42:00 【问题描述】:

我看过这个 SO 问题(这不是重复的):Python bare asterisk in function argument

在 python-3.x 中,您可以在函数参数中添加一个裸露的 *,这意味着(引用自 docs):

“*”或“*identifier”之后的参数是关键字参数,并且 只能传递使用过的关键字参数。

好的,所以,我已经定义了一个函数:

>>> def f(a, b, *, c=1, d=2, e=3):
...     print('Hello, world!')
... 

我只能通过指定关键字来传递cde变量值:

>>> f(1, 2, 10, 20, 30)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 5 were given
>>> f(1, 2, c=10, d=20, e=30)
Hello, world!

问题是:

这种限制/语法糖的动机是什么? 它涵盖了哪些用例? 真的用在切换到python3的第三方库中了吗?

一些“现实世界”的例子会有很大帮助。提前致谢。

【问题讨论】:

适用于需要命名参数以增强可读性的情况,例如一个窗口:Window(width = 800, height = 600, fullscreen = true) PEP 3102 解释得很清楚。 @BrenBarn 谢谢你的链接,它对“动机”部分有很大帮助。真实世界的示例和用例将完成该主题。 据我所知,curio 正在其new_tasks 函数中使用此功能 这里的回复给出了直观的解释:***.com/a/39284225/1436851 【参考方案1】:

PEP 3102 非常清楚地解释了基本原理:关键是允许函数接受本质上正交的各种“选项”。在定义端和调用端指定这些位置都很尴尬,因为它们没有任何明显的“优先级”可以转化为位置顺序。

在各种库中有很多可以从中受益的函数示例。比如pandas.read_csv的调用签名是:

def parser_f(filepath_or_buffer,
                 sep=sep,
                 dialect=None,
                 compression=None,

                 doublequote=True,
                 escapechar=None,
                 quotechar='"',
                 quoting=csv.QUOTE_MINIMAL,
                 skipinitialspace=False,
                 lineterminator=None,

                 header='infer',
                 index_col=None,
                 names=None,
                 prefix=None,
                 skiprows=None,
                 skipfooter=None,
                 skip_footer=0,
                 na_values=None,
                 na_fvalues=None,
                 true_values=None,
                 false_values=None,
                 delimiter=None,
                 converters=None,
                 dtype=None,
                 usecols=None,

                 engine='c',
                 delim_whitespace=False,
                 as_recarray=False,
                 na_filter=True,
                 compact_ints=False,
                 use_unsigned=False,
                 low_memory=_c_parser_defaults['low_memory'],
                 buffer_lines=None,
                 warn_bad_lines=True,
                 error_bad_lines=True,

                 keep_default_na=True,
                 thousands=None,
                 comment=None,
                 decimal=b'.',

                 parse_dates=False,
                 keep_date_col=False,
                 dayfirst=False,
                 date_parser=None,

                 memory_map=False,
                 nrows=None,
                 iterator=False,
                 chunksize=None,

                 verbose=False,
                 encoding=None,
                 squeeze=False,
                 mangle_dupe_cols=True,
                 tupleize_cols=False,
                 infer_datetime_format=False):

除了文件路径之外,其中大部分都是正交选项,用于指定如何解析 CSV 文件的不同方面。没有特别的理由说明它们会以任何特定的顺序通过。你会发疯地跟踪这些的任何位置顺序。将它们作为关键字传递更有意义。

现在,您可以看到 pandas 实际上并没有将它们定义为仅关键字参数,大概是为了保持与 Python 2 的兼容性。我想许多库出于同样的原因避免使用该语法。我不知道哪些库(如果有的话)已经开始使用它。

【讨论】:

强制它们成为关键字参数的一个原因是人们不依赖顺序,因此您可以在将来更改它,或添加新关键字,(例如:@987654324 @),从逻辑上讲,它会在 lineterminator 旁边。 哇,这个函数的参数太多了。肯定是设计有问题。 这个函数是如何不写代码的一个很好的例子。 @Wodzu 怎么写更好?【参考方案2】:

对于那些来自或/和使用过ruby的人

下面的python表达式

def f(a, b, *, c=1, d=2, e=3):

类似于

def f(a,b, options=)
  c = options[:c] || 1
  d = options[:d] || 2
  e = options[:e] || 3
end

在红宝石中。

由于python是explicit is better than implicit语言,所以参数中需要* (splat)运算符。

PS:我没用过python,如有错误请指正。

【讨论】:

以上是关于函数参数中裸星号的目的是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

当我在 Visual Studio 中生成以二维数组作为参数的构造函数时,这些星号是啥?

在函数的签名中,如果星号后面没有标识符名称,那么它在 Python 中的含义是啥? [复制]

C++ 中指向 unique_ptr 函数参数的原始指针的目的是啥?

python中的*参数(不带后缀)函数/方法是啥? [复制]

python 函数星号参数说明

Python 函数参数前面一个星号(*)和两个星号(**)的区别