Python函数的位置参数和关键字参数

python3.8引入了仅位置参数

def f(positional_argument, /, positional_or_keyword_argument, *, c):
    pass

#positional_argument                    位置参数
#positional_or_keyword_argument         位置参数和关键字参数
#keyword_argument                       关键字参数

位置参数(positional) 和 关键字参数(keyword)

函数定义时确定了五种参数, 但可以简化为两种基本类型, 其余的都可以在此基础上进行引申:

基本类型:

  • 位置参数(positional): 传参时前面不带 "变量名=", 顺序不可变, 按顺序赋给相应的局部变量。
  • 关键字参数(keyword): 传参时前面加上 "变量名=", 顺序可变, 按名称赋给同名的局部变量。

引申五种参数

  • 仅位置参数(positional-only):
    / 之前定义的参数, 传参时不带变量名。这个在 python 3.8 中可以自己定义, 不过内置函数早已经使用这种方法了, 可参考 help() 输出的内部函数说明。

  • 位置或关键字参数(positional_or_keyword):
    / 后面和 * 号前面定义的参数, 即我们自定义函数时最常用的。 传参时可以把它当作位置参数或关键字参数看待, 可以带变量名也可以不带。 这就是我们自定义的函数与内置函数的区别之处了, 这一点最迷惑人。

  • 仅关键字参数(keyword-only):
    * 后面定义的参数(或在 *args 后面定义, ... 类似于 *args)。 传参时必需带变量名。

  • 集合位置参数(var_positional):
    即函数定义时采用 *args 指定的参数. 我们一般都把它理解为"可变参数", 实际上理解为"集合位置参数"最精确. 传参时不能带变量名.

    注意: 根据"关键字参数不能在位置参数前面"的原则, *args 会将之前的参数全部转化为 位置参数, 之后的参数全部转化为 关键字参数

  • 集合关键字参数(var_keyword):
    即函数定义时采用 **args 指定的参数。它可以接受我们传入的任意个数的关键字参数。 传参时必须带变量名。

注意: 传递参数时, "关键字参数不能在位置参数前面", 否则就会报错。 根据这条原则, 那么上述顺序也应该是 parameter 定义的顺序了。

另外根据定义时是否有默认参数, 又可分为两种修饰类型, 它们不影响参数的基本类型定义:

  • 必需参数: 定义时没有默认值的参数, 调用时不可省略.
  • 可选参数: 定义时有默认值的参数, 调用时可省略.

集合位置参数和集合关键字参数的比较

集合位置参数(VAR_POSITIONAL)

通过一个*前缀来声明,如果看到一个*xxx的函数参数声明,那一定是属于VAR_POSITIONAL类型的,如同语义,这种类型的参数只能通过位置POSITIONAL传参调用,不支持关键字KEYWORD传参,在函数内部,VAR_POSITIONAL类型的参数以一个元组(tuple)显示,有一点需要注意的,VAR_POSITIONAL类型可以不传任何参数调用也不会报错,而且只允许存在一个。以下是一个简单的例子:

def f(*b):
    print(b)

# 不传参数不会报错,参数值是一个空元祖  
f() # 结果是 ()
# 可以传入任意个位置参数调用
f(1, 2.0, '3', True) #结果是 (1, 2.0, '3', True)

集合关键字参数(VAR_KEYWORD)

VAR_KEYWORD类型的参数通过**前缀来声明。这种类型的参数只能通过关键字KEYWORD调用,但可以接收任意个关键字参数,甚至是0个参数,在函数内部以一个字典(dict)显示。VAR_KEYWORD类型的参数只允许有一个,只允许在函数的最后声名。以下是简单的例子:

def f(**d):
    print(d)

# 不传参数不会报错,参数值是一个空字典
f() # 结果是 {}
# 可以传入任意个关键字参数调用
f(a=1, b=2.0, c='3', d=True) # 结果是 {'a': 1, 'b': 2.0, 'c': '3', 'd': True}

默认参数

  • VAR类型不允许设置默认参数 POSITIONAL_ONLY、POSITIONAL_OR_KEYWORD和KEYWORD_ONLY可以自定义默认参数,而VAR_POSITIONAL和VAR_KEYWORD不允许自定义默认参数的,因为VAR_POSITIONAL的默认参数是tuple()空元祖,而VAR_KEYWORD的默认参数是dict()空字典。
  • 默认参数的位置 POSITIONAL_OR_KEYWORD类型的默认参数一定要放在后面,否则会报错,KEYWORD_ONLY虽然没有强制要求,因为都是用关键字传参,谁先谁后都无所谓,但最好还是尽可能地放在后面吧。
  • 默认参数绝对不能设置为可变类型(比如list, dict, set),如果你在函数内改变了默认参数,下次再调用时它就不再是默认值了。

/*在参数中的使用的语法

def name(positional_or_keyword_parameters, *, keyword_only_parameters):

def name(positional_only_parameters, /, positional_or_keyword_parameters,*, keyword_only_parameters):
  • /左边的参数被视为仅位置参数
  • 如果函数定义中/没有指定,则函数中所有参数都不是仅位置参数
  • 仅位置参数的可选值的逻辑与位置-关键字参数的逻辑相同。
  • 一旦使用默认值指定了仅位置参数,下面的仅位置参数和位置-关键字参数也需要具有默认值。
  • 没有默认值的仅位置参数在调用的时候必需给值。

因此下列属于有效函数定义:

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, /):
def name(p_or_kw, *, kw):
def name(*, kw):

下面属于无效定义

def name(p1, p2=None, /, p_or_kw, *, kw):
def name(p1=None, p2, /, p_or_kw=None, *, kw):
def name(p1=None, p2, /):

函数参数使用举例说明

def f(a, b, /, c, d, *, e, f):
    print(a, b, c, d, e, f)

# a, b 是 仅位置参数;c, d 是 位置或关键字参数; e, f 是 仅关键字参数;

下面是合法调用:

f(10, 20, 30, d=40, e=50, f=60)

非法调用:

f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument 
f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument

可选的位置参数 (python 3.8)

def f(a=2, /): pass
f()         # 允许调用方式,参数是可选的
f(1)        # 允许调用方式,参数是位置参数
f(a=1)      # 错误的调用方式,参数是仅位置参数

必需的位置参数 (python 3.8)

def f(a, /): pass
f()         #错误,需要参数
f(1)        # 正确
f(a=1)      # 错误的调用方式,参数是仅位置参数

可选的关键字参数

def f(*, a=1): pass
f()         # 正确
f(1)        # 错误,参数是仅关键字参数
f(a=1)      # 正确

必需的关键字参数

def f(*, a): pass
f()         # 错误,需要传入参数
f(1)        # 错误,仅关键字参数
f(a=1)      # 正确

可选的位置和关键字参数

def f(a=1): pass
f()         # 正确
f(1)        # 正确
f(a=1)      # 正确

必需的位置和关键字参数

def f(a): pass
f()         # 错误,需要传入参数
f(1)        # 正确
f(a=1)      # 正确

结论:一个参数可以是可选的,也可以是必需的,但不能同时包含这两个参数。它也可以是位置的,关键字的,或者两者同时存在。

关于parameterargument 的理解

parameter 为函数定义时的叫法, 它指明了函数可以接受的argument类型.
argument 为函数调用时的叫法, 可以理解为实参, 即传入的值

参考链接

转载自:https://zhuanlan.zhihu.com/p/412273465

欢迎指正、交流 ~ ~ ~

作者:Jaren
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议
转载请注明文章地址及作者哦 ~
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇