英文:
Asking a detailed guideline to forece parameters as positional-only, positional- or keyword-argument, and keyword only when using *args and **kwargs
问题
https://docs.python.org/3/tutorial/controlflow.html#special-parameters
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| Positional or keyword |
| - Keyword only
-- Positional only
根据文档,/ 和 * 表示参数的类型,根据参数如何传递给函数来决定:仅位置参数、位置或关键字参数以及仅关键字参数。
在使用普通位置参数或关键字参数时,如何使用是明显的。但是,当与 *args
或 **kwargs
一起使用时,对我来说变得很复杂。
例如,
def func(a, *args, /): # SyntaxError: / must be ahead of *
pass
这段代码引发了 SyntaxError: / must be ahead of *
,尽管很明显 a
和 args
是位置参数。我知道这里不需要 /
,但我想知道错误消息为什么是 SyntaxError: / must be ahead of *
。我使用 *
来指出 *args
,而不是独立的 *
。
def func(a, /, *args): # No error!?
pass
然而,这段代码却可以正常工作,尽管 *args
被指定为位置或关键字参数,因为它跟随在 /
之后(*args
不能接受关键字参数!)。我认为这应该引发错误,如 SyntaxError: *args cannot take keyword argument
。
此外,
def func(*, **kwargs): # SyntaxError: named arguments must follow bare *
pass
这段代码引发了 SyntaxError: named arguments must follow bare *
。我知道在函数中 *
是不必要的,但错误消息说命名参数必须跟在裸 *
后面,尽管命名参数 **kwargs
已经跟在 *
后面了。
我觉得我可能遗漏了某些内容。因此,如果有人能更详细地解释如何在使用 *args
或 **kwargs
时使用 /
和 *
,将不胜感激。
英文:
https://docs.python.org/3/tutorial/controlflow.html#special-parameters
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| Positional or keyword |
| - Keyword only
-- Positional only
According to the reference, / and * indicate the kind of parameter by how the arguments may be passed to the function: positional-only, positional-or-keyword, and keyword-only.
It is clear how to use it when I use normal positional arguments or keyword arguments. However, when I use *args
or **kwargs
together, it becomes very complicated to me.
for example,
def func(a, *args, /): # SyntaxError: / must be ahead of *
pass
This code raise SyntaxError: / must be ahead of *
although it is clear that a
and args
is positional parameters. I know / is unnecessary here, but what I am wondering is why the Error message is SyntaxError: / must be ahead of *
. I used *
for to point out *args
, not independent *
.
def func(a, /, *args): # No error!?
pass
However, this code works without Error although *args
is indicated as positioal- or keyword- arguments as it follows /
(*args
cannot take keyword arguments!). I think this should raise Error such as SyntaxEror: *args cannot take keyword argument
.
In addition,
def func(*, **kwargs): # SyntaxError: named arguments must follow bare *
pass
This code raise SyntaxError: named arguments must follow bare *
. I know in the function, *
is unnecessary, but the error message says named arguments must follow bare * although the named arguments **kwargs
is already following *
.
I think I am missing something. So, it would very appreciate if anyone explain more detailed guideline to use /
and *
when using *args
or **kwargs
.
答案1
得分: 1
以下是您要翻译的内容:
答案非常简单:错误消息看起来很奇怪,但实际上工作与不工作是非常合乎逻辑的。
请记住,如果您同时使用制表符和空格的混合,可能会出现“错误:无效常数”。解析器并不总是能够明白为什么某些东西不起作用。此外,您对“/”的工作原理有一些误解。
*args
接受所有位置参数
**kwargs
接受所有关键字参数。
因此,如果您定义一个这样的函数:
def func(a, *args, /): # 语法错误:/ 必须在 * 之前
pass
您实际上做了相同的事情。/
禁止了更多的位置参数,但 *args
已经接受了所有位置参数,所以斜杠是不必要的。
对于 *, **kwargs
也是一样的。*
不是必需的。
但是,以下代码可以工作:
def hello(*, hello: str = "Hello", **kwargs):
print(kwargs)
在这种情况下,需要使用 *,否则 hello
可以被按位置传递。因此,这也可以工作。解析器只检查是否存在一个定义来接受 *
后面的变量,而 **kwargs 不包含这一点,这不被视为错误,因为没有必要以这种方式使用它。
最后,我同意这样的代码:
def func(a, /, *args): # 没有错误!?
pass
很奇怪,但它确实可以工作:
/
禁止将任何东西放在它前面作为关键字传递,而 *
要求在它后面接受关键字。您可以在 /
后面传递位置参数,*args 会接受它们。
这是完全有效的 Python 代码:
def hello(a, /, *args):
print(args)
print(a)
hello("a", "b")
>>> ('b',)
>>> a
因此,这是顺序:
(位置参数, 仅位置, /, 位置或关键字, [*args或*], 仅关键字, **kwargs)
如果您指定了 *
然后是 **kwargs
,而没有其他内容,它会引发额外的错误,因为不需要 *
。
您收到的错误消息确实有点奇怪,但一切都是合理的。
希望这对您有所帮助。
英文:
The answer to this question is really simple: The error messages are weird, however, what works and what does not is really logical.
Keep in mind that, if you are using a mixture of tabs and spaces, you can get an error: invalid constant.
The parser is not always able to see why something does not work. Also, you kind of misunderstand how /
works.
*args
eats up all positional arguments
**kwargs
eats up all keyword arguments.
So, if you define a function like this:
def func(a, *args, /): # SyntaxError: / must be ahead of *
pass
You're doing the same thing twice. /
prohibits any more locational arguments, but *args
already eats up all of them, so the slash is not needed.
Same goes for *, **kwargs
. *
just not needed.
This, however, does work:
def hello(*, hello: str = "Hello", **kwargs):
print(kwargs)
At this point, the * is needed, as otherwise hello
could be passed positionally. This, therefore also works. The parser just checks if there is a definition to take variables after the *
, and **kwargs does not, and this is not seen as a bug, because there is no need to use it that way.
Lastly, I agree that this:
def func(a, /, *args): # No error!?
pass
Is weird code, but it does work:
the /
prohibits anything in front of it to be passed as a keyword, and *
mandates anything after it to be taken as a keyword. You can pass positional arguments after a /
, and *args will eat those up.
This is perfectly valid python:
def hello(a, /, *args):
print(args)
print(a)
hello("a", "b")
>>> ('b',)
>>> a
So, this is the order:
(positional, only, /, positional or keyword, [*args or *], keyword only, **kwargs)
Where, if you specify a *
and then **kwargs
without anything in between, it throws an additional error, because the * was not needed.
The error messages you get are indeed a bit weird, but it does all check out.
I hope that helps.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论