Asking a detailed guideline to forece parameters as positional-only, positional- or keyword-argument, and keyword only when using *args and **kwargs

huangapple go评论70阅读模式
英文:

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 *,尽管很明显 aargs 是位置参数。我知道这里不需要 /,但我想知道错误消息为什么是 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,而没有其他内容,它会引发额外的错误,因为不需要 *

您收到的错误消息确实有点奇怪,但一切都是合理的。

希望这对您有所帮助。 Asking a detailed guideline to forece parameters as positional-only, positional- or keyword-argument, and keyword only when using *args and **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. Asking a detailed guideline to forece parameters as positional-only, positional- or keyword-argument, and keyword only when using *args and **kwargs

huangapple
  • 本文由 发表于 2023年4月11日 16:58:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75984086.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定