函数参数中裸星号的目的是什么? [英] What is the purpose of a bare asterisk in function arguments?

查看:42
本文介绍了函数参数中裸星号的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我见过这个 SO 问题(这不是重复的):Python 裸函数参数中的星号

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

<块引用>

*"或*identifier"后面的参数是关键字参数,只能传递使用过的关键字参数.

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

<预><代码>>>>def f(a, b, *, c=1, d=2, e=3):...打印('你好,世界!')...

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

<预><代码>>>>f(1, 2, 10, 20, 30)回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中类型错误:f() 需要 2 个位置参数,但给出了 5 个>>>f(1, 2, c=10, d=20, e=30)你好,世界!

问题是:

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

一些真实世界"的例子会有很大帮助.提前致谢.

解决方案

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

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

def parser_f(filepath_or_buffer,sep=sep,方言=无,压缩=无,双引号=真,转义符=无,报价字符='"',报价= csv.QUOTE_MINIMAL,跳过初始空间=假,换行符=无,标题='推断',index_col=无,名称=无,前缀=无,跳过=无,跳脚=无,skip_footer=0,na_values=无,na_fvalues=无,true_values=无,false_values=无,分隔符=无,转换器=无,dtype=无,usecols=无,引擎='c',delim_whitespace=假,as_recarray=假,na_filter=真,compact_ints=假,use_unsigned=假,low_memory=_c_parser_defaults['low_memory'],buffer_lines=无,warn_bad_lines=真,error_bad_lines=真,keep_default_na=真,千=无,评论=无,十进制=b'.',解析日期=假,keep_date_col=假,第一天=假,date_parser=无,memory_map=假,nrows=无,迭代器=假,块大小=无,详细=假,编码=无,挤压=假,mangle_dupe_cols=真,tupleize_cols=假,infer_datetime_format=False):

除了文件路径之外,大多数都是正交选项,用于指定如何解析 CSV 文件的不同方面.没有特别的理由为什么它们会以任何特定的顺序传递.你会疯狂地跟踪这些的任何位置顺序.将它们作为关键字传递更有意义.

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

I've seen this SO question (this is not a duplicate): Python bare asterisk in function argument

In python-3.x you can add a bare * to the function arguments, this means that (quote from docs):

Parameters after "*" or "*identifier" are keyword-only parameters and may only be passed used keyword arguments.

Ok, so, I've defined a function:

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

I can pass c, d and e variable values only by specifying keywords:

>>> 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!

Questions are:

  • What is the motivation for this kind of restriction/syntax sugar?
  • What use cases does it cover?
  • Is it really used in third-party libraries that switched to python3?

Some "real-world" examples would help a lot. Thanks in advance.

解决方案

PEP 3102 explains the rationale pretty clearly: the point is to allow functions to accept various "options" that are essentially orthogonal in nature. Specifying these positionally is awkward both on the defining and calling side, since they don't have any obvious "priority" that would translate into a positional order.

There are lots of example of functions that would benefit from this in various libraries. For instance, the call signature of pandas.read_csv is:

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):

Except for the filepath, most of these are orthogonal options that specify different aspects of how a CSV file is to be parsed. There's no particular reason why they would be passed in any particular order. You'd go nuts keeping track of any positional order for these. It makes more sense to pass them as keywords.

Now, you can see that pandas doesn't actually define them as keyword-only arguments, presumably to maintain compatibility with Python 2. I would imagine that many libraries have refrained from using the syntax for the same reason. I don't know offhand which libraries (if any) have started using it.

这篇关于函数参数中裸星号的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆