彻底弄懂 Python3中入参里的*号的作用

目录

Python3中几种传递参数的方式:

1.位置参数

2.默认参数

3.关键字参数

4.可变参数

5.keyword-only参数

6.参考链接


我们在看代码时,除了能看到普通的定义函数的入参写法,比如 def func(param1, param2): ,可能也会看到入参用 *args, **kwargs 来代替的写法,比如 def func(*args, **kwargs):,此外还有一种写法,比如 def func(param1, *, param2):,中间多了一个单纯的星号,这个用法又是什么意思呢?先从Python中的几种传递参数的方式说起。

Python3中几种传递参数的方式:

位置参数、默认参数、关键字参数、可变参数(包括可变位置参数,可变关键字参数)、keyword-only参数(命名关键字参数)

1.位置参数

位置参数是最普通、最常见的传参方式,位置参数必须按照先后顺序传入,传入的参数和定义时的参数,一一对应,例如下面的“1”传给了param1,“2”传给了param2:

def func(param1, param2):
    print("param1:", param1)
    print("param2:", param2)


if __name__ == '__main__':
    func(1, 2)

# 输出:
# param1: 1
# param2: 2

2.默认参数

默认参数也比较常见,函数定义时给某个参数设置默认值,调用函数时如果不传这个参数,就使用默认值,如果传了就用传入值:

def func(param1, param2=1):
    print("param1:", param1)
    print("param2:", param2)


if __name__ == '__main__':
    print("未传入默认参数时")
    func(1)
    print("传入默认参数时")
    func(1, 2)

# 输出:
# 未传入默认参数时
# param1: 1
# param2: 1
# 传入默认参数时
# param1: 1
# param2: 2

但是这里要注意,定义函数时如果同时有位置参数和默认参数,默认参数一定要在普通参数的后面,否则会报错如。这是Python语法规定,其实也很好理解,如果不规定顺序,像下面这个函数 def func(param1, param2=1, param3): ,如果传入2个参数,func(1, 2),这个“2”是传给param2的还是param3的会有歧义。

使用默认参数还有一个需要注意的地方,默认参数的默认值尽量使用不可变对象,param2=1、param2="txt"这种,否则会引起意想不到的问题。关于不可变对象可以参考:Python中的不可变对象和可变对象

3.关键字参数

关键字参数其实不能单独算作一类参数,是Python中比较方便的一个传参方式。就是在调用函数时,指定将哪个实参传给哪个形参,当然指定的形参名字必须是函数定义时所用的名字。其实普通的位置参数、默认参数、可变参数、keyword-only参数都可以用关键字参数的方式传参。

def func(a, b,  c=3, d=4):
    print("a:", a)
    print("b:", b)
    print("c:", c)
    print("d:", d)


if __name__ == '__main__':
    func(1, 2, 3, 4)
    func(1, 2, 3, d=4)
    func(1, 2, c=3, d=4)
    func(1, 2, d=4, c=3)
    func(1, b=2, c=3, d=4)
    func(d=4, c=3, b=2, a=1)

# 输出都是:
# a: 1
# b: 2
# c: 3
# d: 4

4.可变参数

可变参数也叫动态参数,在Python标准库中见到的比较多。使用可变参数传入的参数的个数是动态的,可以是1个、2个到任意个,还可以是0个。

def func(*args, **kwargs):
    print("type of args: ", type(args))
    print("args:", args)
    print("type of kwargs: ", type(kwargs))
    print("kwargs:", kwargs)


if __name__ == '__main__':
    func(1, 2, a=3, b=4)

# 输出
# type of args:  <class 'tuple'>
# args: (1, 2)
# type of kwargs:  <class 'dict'>
# kwargs: {'a': 3, 'b': 4}

可以看到动态参数分两种,一个是*开头,例如*args,另一个是**开头,例如**kwargs。其中args和kwargs完全可以像其他参数一样自己命名,只是约定俗成的用*args和**kwargs,使用这两个IDE也会自动联想补全。args的类型是元组,调用函数时可以传入任意多的参数,这些参数会自动封装到args里,成为一个元组。kwargs的类型是字典,调用函数时可以传入任意多的自定义键值对参数,这些参数会自动封装到kwargs里,成为一个字典。

用*args,**kwargs组合的方式理论上可以传入任意值,许多标准库代码都是这样写的,*args必须写在**kwargs前面。但是我觉得如果真的所有函数入参都这样写,代码看起来会比较难懂,还是尽量不用这种方法。

那么在函数里面args和*args,kwargs、*kwargs、**kwargs有什么区别呢?可以试一下对比看看,下图中可以看出,*号在这里只是一个标识作用,是给解释器看的,相当于把元组和字典的键的内容取出来,不用太纠结这个,就是一种规定。

同样可变参数位置参数和默认参数使用时也要注意顺序:位置参数、默认参数或*args、**kwargs。也就是说下面这两种方式都是可以的:

5.keyword-only参数

keyword-only参数是Python3中新加入的特性,比较不多见。

定义时有一个单独的*号,其实这也只是一种规定,*号看上去像是一个参数,其实它不占参数个数,是给解释器看的。规定*号后面的参数,能且只能用key=value的方式传入,也就是上面第3步那种关键字参数传参形式。

def func(a, b, *, c=3, d=4):
    print("a:", a)
    print("b:", b)
    print("c:", c)
    print("d:", d)


if __name__ == '__main__':
    func(1, 2, c=3, d=4)

# 输出:
# a: 1
# b: 2
# c: 3
# d: 4

上面这个函数如果没有单独的星号,我们可以 func(1, 2, 3, 4), func(1, 2, c=3, 4), func(1, 2, c=3, d=4)这样调用,而有了这个星号标识,就只能用 func(1, 2, c=3, d=4) 这种方式调用。

6.参考链接

Python参数类型——刘江

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值