Python函数参数探索

最近碰到一个问题,就是函数参数类型怎么判断,是否就是我们定义函数时就已经确定了的?
def foo(a, b=0, *args, **kwargs):
    print(a)
    print(b)
    print(args)
    print(kwargs)

按照网上资料,普遍的说法

  • 位置参数:a
  • 默认参数:b
  • 接收任意数量位置参数:args
  • 接收任意数量关键字参数:kwargs

然后我也一直这么认为的,但是事情并没有这么简单,不记得因为什么开始对这个参数类型产生了疑惑,遂在网上搜索Python关键字参数等相关文章博客,主要有以下几种形式:

# **kwargs接收任意数量
def foo1(a, b=10, **kwargs):
    pass

def foo2(a):
    pass

def foo3(a, b=10):
    pass

foo1(10, 20, c=30, d=40)
foo2(a=10)
foo3(a=10, b=10)

这个时候我就纳闷了,如果一开始函数定义时,参数类型是固定的话,那为什么有的文章里举例的时候,用到了foo(args1=value1, args2=value2,…)的这种形式,所以我不理解:关键字参数不是被**kwargs接收的么,那为什么这种形式也叫关键字参数呢? 而我问了一些人之后,有的人说参数类型怎么会因为参数传入形式不同而变化呢?(这个说法应该是有问题的)

后来我查了《Effective Python》中文版的(因为刚好在手边),第19条:用关键字参数来表达可选的行为

def foo(a, b, c=30, d=40):
    pass

里面举例的时候用到了类似这种形式的函数(简写了函数名称及参数名称),foo(10,20, c=300, d=400)这种调用方式,这里c、d书里说这两个是可选的关键字参数
看到这里,我明确了一点:关键字参数应该不是由**kwargs这种接收方式所决定的

1、函数参数可以按位置或关键字来指定
2、…可以使用带有默认值的关键字参数…
3、python函数中的所有位置参数,都可以按关键字传递

  1. 引用块内容
def foo(a, b):
    print(a)
    print(b)


foo(b=10, 10)
#    foo(b=10, 10)
#             ^
#SyntaxError: positional argument follows keyword argument

foo(a=10, 10)
#    foo(a=10, 10)
#             ^
#SyntaxError: positional argument follows keyword argument

foo(c=10, 10)
#    foo(c=10, 10)
#             ^
#SyntaxError: positional argument follows keyword argument

看到这里,有以下几个可以确认的:

  1. 函数参数有两种传入方式:
    a、按位置/按关键字,其中按位置就是从前往后,依次接收传入的参数;
    b、而按关键字就是key=value这种形式,这种情况就是指定将value传给指定的key,如果原函数参数有**kwargs表达式的话,那key可以在原函数中不存在,反之如果没有**kwargs接收,那就会报错了
  2. 关键字参数后不能有位置参数,如上面几个调用形式foo(c=10, 10),解释器报错时,这条提示信息的优先级高于foo(c=10,d=10) # TypeError: foo() got an unexpected keyword argument 'c'这个错误
  3. **kwargs =/= 关键字参数,kwargs只是用来接收关键字参数,也就是这种(key=value)形式的参数
  4. 当一个参数在前面按位置接收了一个对象后,后面接着以key=value第二次传入对象时,这里就会报错foo(10, a=10) #TypeError: foo() got multiple values for argument 'a'

下面有几个大胆的推测(尚不确定):

  1. 函数定义时的参数(a, b=10, *args, **kwargs)应该只是用来接受参数的(“容器”)
  2. 参数类型是和传入方式有关系的,以key=value形式传入应该都是关键字参数

《Python Cookbook 3》中有一个例子-强制接收关键字

# python3,据说python2不支持,拥抱python3,和python2saygoodbye吧!
def foo(a, b, *, c, d):
    pass
foo(10, b=10, ... , c=30, d=40)

这个例子里面,调用函数时传入的参数(c、d)必须以key=value的形式传入,所以前面的推测应该是对的

总结:
1、函数定义时定义的是参数名称,不是参数类型,参数类型是由传入方式决定的
2、默认参数也叫可选关键字参数,这种类型比较特殊,因为一开始函数定义时就以key=value的形式让key指向value了
3、知道怎么处理参数就好了,对这些概念不要过于纠结
4、以上内容只是个人想法,可能有的地方理解错误,希望知道的网友能指点迷津

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值