相关阅读
Python专栏https://blog.csdn.net/weixin_45791458/category_12403403.html?spm=1001.2014.3001.5482
函数定义就是定义一个用户自定义的函数对象,它的语法的BNF范式如下所示,有关BNF范式的规则,可以参考之前的文章。
- funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
- ["->" expression] ":" suite
- decorators ::= decorator+
- decorator ::= "@" assignment_expression NEWLINE
- parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]
- | parameter_list_no_posonly
- parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]
- | parameter_list_starargs
- parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
- | "**" parameter [","]
- parameter ::= identifier [":" expression]
- defparameter ::= parameter ["=" expression]
- funcname ::= identifier
函数定义是一个可执行语句。它的执行将当前本地命名空间中的函数名绑定到一个函数对象(该函数的可执行代码的包装器)。此函数对象包含对当前全局命名空间的引用,作为调用函数时要使用的全局命名空间。
其中参数列表的第一种情况是由/分隔的两部分,其中前半部分是至少一个可以带默认值的形参,被称作defparameter,但它们有位置实参限制,即只能使用位置传递参数,后半部分是无位置限制的参数列表。在第二种情况下,参数列表也可以只有无位置限制的参数列表这一部分组成。
无位置限制的参数列表的第一种情况是,至少一个defparameter和后面的带星参数列表。在第二种情况下,参数列表也可以只有带星参数列表。
带星参数列表的第一种情况是,一个"*"加可选的带单星形参,后面有若干个defparameter,在这之后,还可以有一个"**"加带双星形参。在第二种情况下,参数列表也可以只有一个"**"加带双星形参。带单星形参和带双星形参不能给予默认值,它们分别被用来接收函数调用时多余的位置实参和关键词实参。
注意,以上说的形参都是用逗号分隔的,且参数列表的最后可以额外加一个逗号。此外,如果一个形参具有默认值,则后续所有在形参列表中第一个"*" 或 "**" 之前的形参也必须具有默认值,但这个句法限制并未在BNF语法中明确表达,这是为了更好地解析实参(值得一提的是,当参数列表里面并不存在"*" 或 "**" 时,所有具有默认值的形参后面的形参也必须具有默认值)。
带星形参之后的其他形参只能通过关键词实参传入,与/前的情况相反,这很好理解,因为带星形参会接受所有多余的位置实参而不会给它之后的形参留下任何实参。
虽然上面的内容比较繁杂,但实际上使用次数最多的形参定义格式只有几种:位置形参、关键词形参、带星形参、带双星形参以及它们的组合。
下面的代码段列出了多种不同的合法函数形参定义形式,对应的描述如注释所示。
- def fun(a, b, c=1, d=0):
- pass # c和d有默认值
-
- def func(a, b, /, c=1, d=0):
- pass # a和b只能通过位置实参传入,c和d有默认值
-
- def func(a, b, c, d):
- pass
-
- def func(a, b, /, c, d):
- pass # a和b只能通过位置实参传入
-
- def func(a, b, *c, **d):
- pass # c和d用来接收多余的位置实参和关键词实参
-
- def func(a, b, /, *c, **d):
- pass # a和b只能通过位置实参传入,c和d用来接收多余的位置实参和关键词实参
-
- def func(a, b, *c, d, **e):
- pass # 带*参数后可以有若干个形参,d只能通过关键词传入,c和d用来接收多余的位置实参和关键词
- # 实参
-
- def func(a=1, b=0, /, *c, **d):
- pass # a和b只能通过位置实参传入,且有默认值,c和d用来接收多余的位置实参和关键词实参
-
- def func(a, b=1, *c, d, **e):
- pass # d只能通过关键词传入,且不是必须有默认值
-
- def func(a, b, **d):
- pass # d用来接收多余的关键词实参
-
- def func(a, b, *c, d=1, **e):
- pass # 带*参数后可以有若干个形参,d只能通过关键词传入且有默认值,c和d用来接收多余的位
- # 置实参和关键词实参
-
- def func(a, b, *c, d=1, f, **e):
- pass # 带*参数后可以有若干个形参,d只能通过关键词传入且有默认值,f只能通过关键词传入
- #(这里可以没有默认值,因为是第二个*或**,c和d用来接收多余的位置实参和关键词实参
下面的文章还介绍了函数调用的实参相关问题,欢迎浏览。
Python:函数调用的实参https://mp.csdn.net/mp_blog/creation/editor/132912878