Python3.8中仅带位置参数的角盒?

Python3.8中仅带位置参数的角盒?,python,arguments,python-3.8,default-arguments,pep570,Python,Arguments,Python 3.8,Default Arguments,Pep570,我正在摆弄中指定的和中介绍的仅用于位置的参数,我只是想知道一个具体的拐角情况 假设我定义了一个函数,如下所示(无论这是好的设计还是有意义): def func(p1,p2=None,p3=None,/): 打印(p1、p2、p3) 因此,有一个必需参数(p1),后面是两个可选参数(p2和p3)。我可以用p1、p1和p2或p1和p2和p3调用函数: func(1) # 1, None, None func(1, 2) # 1, 2, None func(1, 2, 3) # 1

我正在摆弄中指定的和中介绍的仅用于位置的参数,我只是想知道一个具体的拐角情况

假设我定义了一个函数,如下所示(无论这是好的设计还是有意义):

def func(p1,p2=None,p3=None,/):
打印(p1、p2、p3)
因此,有一个必需参数(
p1
),后面是两个可选参数(
p2
p3
)。我可以用
p1
p1
p2
p1
p2
p3
调用函数:

func(1)       # 1, None, None
func(1, 2)    # 1, 2, None
func(1, 2, 3) # 1, 2, 3
但是我不可能只使用
p1
p3
的参数调用它,同时保留
p2
的默认值,因为我不能提供关键字参数:

func(1, p3=3)
def name(p1, p2, /, p_or_kw, *, kw):
def name(p1, p2=None, /, p_or_kw=None, *, kw):
def name(p1, p2=None, /, *, kw):
def name(p1, p2=None, /):
def name(p1, p2, /, p_or_kw):
def name(p1, p2, /):
这当然会引起
类型错误

TypeError: func() got some positional-only arguments passed as keyword arguments: 'p3'
我找不到关于此案例的任何讨论或示例,因为中的所有示例仅包含一个可选参数作为仅位置参数的一部分:

func(1, p3=3)
def name(p1, p2, /, p_or_kw, *, kw):
def name(p1, p2=None, /, p_or_kw=None, *, kw):
def name(p1, p2=None, /, *, kw):
def name(p1, p2=None, /):
def name(p1, p2, /, p_or_kw):
def name(p1, p2, /):
所以我的问题是:这是一个预期的行为,让调用者从左到右提供多个可选参数,以强制顺序覆盖它们吗?这实际上是纯位置参数的一个特性吗

让调用者从左到右提供多个可选参数,并以强制顺序覆盖它们,这是预期的行为吗?这实际上是纯位置参数的一个特性吗

这不仅是位置参数的“预期行为”,而且是它的定义

func(1,p3=3)
直接与函数签名中使用的
/
相矛盾,因为它为只接受位置参数的函数提供关键字参数。
p2
有一个默认值这一事实是不相关的(尽管正如您所发现的,它几乎是无用的)

我将继续在文档中寻找明确的解释,但可能没有。这基本上是使用
/
的直接含义

但是,:

这表明我们可以将
func
改写为:

def func(p1,p3=None, /, p2=None):
    print(p1, p2, p3)
那么这两项工作:

func(1, 3)
func(1, 3, 2)
输出为

1 None 3
1 2 3

一个很好的例子就是
eval
内置参数,它有两个仅限位置的可选参数:

func(1, p3=3)
def name(p1, p2, /, p_or_kw, *, kw):
def name(p1, p2=None, /, p_or_kw=None, *, kw):
def name(p1, p2=None, /, *, kw):
def name(p1, p2=None, /):
def name(p1, p2, /, p_or_kw):
def name(p1, p2, /):
eval(源,全局=None,局部=None,/)
在全局和局部上下文中评估给定源。
源可以是表示Python表达式的字符串
或由compile()返回的代码对象。
全局变量必须是字典,局部变量可以是任何映射,
默认为当前全局值和局部值。
如果只提供全局变量,则局部变量默认为全局变量。
因此,没有办法只指定
本地人

eval(“1+2+x”,局部变量={'x':3}) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:eval()不接受关键字参数
在位置上,必须首先提供
globals
(如果省略
locals
,它们默认为
globals
):

。。。或者,如果它们之间存在差异:

>>> eval("1 + 2 + x", {'x': 3}, {'x': 4})
7

因此,为了回答这个问题:这正是预期的行为。

“这就是预期的行为,让调用者从左到右提供多个可选参数,以强制顺序覆盖它们吗?这实际上是仅位置参数的特性吗?”
我可能无法正确理解您的意思,但这不仅仅是位置参数的“预期行为”,几乎就是它的定义。
func(1,p3=3)
直接与函数定义中使用的
/
相矛盾,因为它为只接受位置参数的函数提供了关键字参数。
p2
具有默认值的事实是不相关的>func(1,p3=3)直接与/yeah的用法相矛盾,这只是为了说明只重写一个默认参数是不可能的。我只是对仅位置参数中的多个默认值感到困惑,但这似乎是您实际想要的行为。我只是发现没有对该行为的显式引用。使用位置参数或关键字参数呃,有一个概念是“这里有一些有意义的默认值,如果你想的话,你可以单独覆盖它们”,而对于positional,也有默认值,但更像是“这里有一些默认值,你可以一个接一个地覆盖它们,但也只能按照我们告诉你的顺序“。我想这是让我困惑的地方,在位置上下文中,默认参数具有不同的语义。但这很有意义,我想问题已经得到了回答。当然,它还可以让人们像
func(1,3,p2=2)
甚至
func(1,p2=2)那样调用它
。但这是另一种签名,因为它将
p2
移动到位置参数或关键字参数中。但无论如何,你是对的,这是预期的行为。我只是被新的语义弄糊涂了,即在仅位置上下文中有多个可选参数,但实际上它是你想要的在l-或-keyword上下文中,调用方可以以任意组合和顺序(如cherry picking)单独传递多个可选参数,而在位置上下文中,只能覆盖默认参数,但只能按照签名施加的顺序从左到右逐个覆盖。这是我以前没有画过的点。