Discuss / Python / 学习过程中的一点收获

学习过程中的一点收获

Topic source

参数定义的顺序必须是:必选参数、默认参数、可变参数/命名关键字参数和关键字参数。

但是我发现可变参数是可以放在必选参数和默认参数前面的,例如:

def test(*a, b, c = 1):
    print("a =", a)
    print("b =", b)
    print("c =", c)

这段定义本身没有报错,但是调用的时候却出问题了,只能把 b 的参数的名字一起传进去才能让解释器区分各个参数:

>>> test(1, 2, 3, b = 4)
a = (1, 2, 3)
b = 4
c = 1

同时做这个测试的时候发现可变参数的优先级是比可选参数高的,上例中如果不把 c 的参数传进去的话,再多的参数都会被归到可变参数 a 里面。

这个测试有些地方理解不对。

如题主所述,定义test函数后:

>>> test(1, 2, 3, 4)

错误提示:

TypeError: test() missing 1 required keyword-only arguments: 'b'

其中,keyword-only命名关键字。所以,才会必须把 b 的名字传进去,因为解释器把 b 理解为命名关键字,而不是必选参数,所以才有如下输出:

>>> test(1, 2, 3, b = 4)
a = (1, 2, 3)
b = 4
c = 1

c 也是如此,不是默认参数,也是命名关键字。比如:

>>> test(1, 2, 3, b = 4, 10)

错误提示:

SyntaxError, non-keyword arg after keyword arg

如果是默认参数,可以修改,那上面的用法不应该出错。但实际上出错了。

注意,在这句提示上面的,b=4 后面的小尖尖。这句话的意思不是说 10 错了,而是说 b=4 后面缺了一个带关键字的参数。

如果按下面的写,就不会出错:

>>> test(1, 2, 3, b = 4, c = 10)
a = (1, 2, 3)
b = 4
c = 10

可见,

参数定义的顺序必须是:必选参数、默认参数、可变参数/命名关键字参数和关键字参数。

这句话并没有错,还是原来的顺序。

再说点题外话:

  • 其实解释器如何解释参数的意义,只能是"固定的"顺序。这跟解释器的实现相关。(如果学过C语言的可变参数是如何设定的,就能更容易理解。)
  • 题主的探索精神是好的,值得肯定。
  • 英文很重要,知道一些概念的中文名,也应该知道英文名。才能更好地理解错误提示。
  • 廖大大可否在关键概念和定义中,加入英文名称?

生健男

#3 Created at ... [Delete] [Delete and Lock User]

为什么我不能发表评论啊?


  • 1

Reply