首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

函数参数有多少(上)

今后的两篇文章为大家带来Python中函数参数的相关内容。函数的参数在前两篇星号表达式中接触过一些,这里将带来比较详细的内容。

我们根据函数的定义和调用两个过程来为参数分类:

函数定义

函数定义时的参数(定义的参数英文叫parameter)可以分为5个大类:

位置或关键字参数(positional-or-keyword)表示该参数可由位置参数关键字参数两种方式调用。

变长位置参数(var-positional,单星号表达式)

变长关键字参数(var-keyword,双星号表达式)

positional-only parameter(很难做合适的翻译,请意会)

表示这个参数只支持位置参数调用,不可以用关键字调用。注意:这只是一个PEP中的提案,还未正式成为Python语言的一部分

keyword-only parameter(翻译同上,有人称其为命名关键字参数或强制关键字参数)

同上面类似,表示这个参数只支持关键字调用,不可以使用位置参数调用。它已经是Python语言的一部分

函数调用

函数调用时传递的参数(调用的参数英文叫argument)可以分为两大类:

位置参数(positional argument)

关键字参数(keyword argument)

下面来结合例子看一下Python的函数参数问题。同其他语言一样,Python可以像这样定义一个非常普通的函数:

deffunc1(a,b,c):

print('a, b, c = {}, {}, {}'.format(a,b,c))因为Python是动态类型语言(注意这里的用词),你可以传任何值给函数参数。这里定义的参数可以位置参数或关键字参数的方式调用(当然可以混合使用):

func1('hi', [1,2,3],func1)# a, b, c = hi, [1, 2, 3], 由于是按参数列表的先后位置读取值,所以称其为位置参数(positional argument)。关键字参数允许你以函数定义时的参数名来传递参数(前面见过很多了):

func1(a=1,b=[1,2,3],c=True)# a, b, c = 1, [1, 2, 3], True而且你可以忽略他们的顺序:

func1(b=[1,2,3],c=True,a=1)# a, b, c = 1, [1, 2, 3], True但是你必须将关键字参数放在位置参数后面:

func1(1,b=[1,2,3],c=True)# a, b, c = 1, [1, 2, 3], True

func1(a=[1,2,3],True,c=1)# SyntaxError: positional argument follows keyword argument(这里是Python 3.6版本的错误信息)关键字参数这个特性为我们带来了极大的便利(正因此,上篇的双星号表达式才可以在函数调用中使用):a. 让函数调用更清晰,更灵活;b. 解除了调用顺序的束缚,调用者只需要知道参数名即可;此外,Python允许你在定义函数时为参数设定默认值,这样这个参数就变成了可选参数。

deffunc1(a,b=1,c='hi'):

print('a, b, c = {}, {}, {}'.format(a,b,c))

func1(1)# a, b, c = 1, 1, hi

func1(1, [1,2,3])# a, b, c = 1, [1, 2, 3], hi后一个例子中,参数列表中传了两个值,则默认参数就被覆盖了。注意,默认值参数也必须放在位置参数后面

deffunc1(a=1,b,c='hi'):

print('a, b, c = {}, {}, {}'.format(a,b,c))

# SyntaxError: non-default argument follows default argument将上面几个特性结合起来,看一个例子:

deffunc2(a,b=1,*args,**kwargs):

print('a = {}, b = {}, args = {}, kwargs = {}'.format(a,b,args,kwargs))

func2(1)

# a = 1, b = 1, args = (), kwargs = {}

func2(1,2,3,c=4)

# a = 1, b = 2, args = (3,), kwargs = {'c': 4}

func2(*range(1,4),**{'d':5,'e':6})

# a = 1, b = 2, args = (3,), kwargs = {'d': 5, 'e': 6}下面重点来看最后两类参数:

keyword-only parameter(先简称它kp)Python允许你在变长位置参数后面定义kp,像这样:

deffunc2(a,b,*args,kwarg):

print('kwarg = {}'.format(kwarg))这样,你必须采用关键字参数调用的方式为赋值:

func2(1,b=2)# TypeError: func2() missing 1 required keyword-only argument: 'kwarg'

func2(1,b=2,kwarg=3)# kwarg = 3你不能采用位置参数的方式,因为所有多余的位置参数都被收走了!当然,如果你只需要一个kp,你可以去掉:

deffunc2(*,kwarg):

print('kwarg = {}'.format(kwarg))这个函数只能接收一个关键字参数:

func2(1,2,kwarg=1)

# TypeError: func2() takes 0 positional arguments but 2 positional argument (and 1 keyword-only argument) were given

func2(kwarg=[1,2,3])# kwarg = [1, 2, 3]

positional-only parameter(先简称它pp)pp并没有在CPython语法层面做实现。但在PEP中有一份参考语法格式:

defname(positional_only_parameters,/,positional_or_keyword_parameters,

*,keyword_only_parameters):这样定义的函数,前面几个参数只能通过位置参数的方式调用。虽然pp语法还未实现,但是Python有一些内建函数却是以pp的方式工作,例如最熟悉的求幂函数,先来看下它的参数列表:

help(pow)# pow(x, y, z=None, /)

# 注意到这个斜杠号了吗

# 参数z用于结果对z取余试着调用一下:

pow(x=2,y=3)# TypeError: pow() takes no keyword arguments

pow(2,3)# 8此外,pp允许你对参数列表进行可选分组,例如更加常见的函数(严格来说,是类

help(range)

# range(stop)

# range(start, stop[, step])可以看到,如果传递了一个参数,则这个参数为,如果两个,则先后。所以更形象一点的定义是。默认值是0。来看看的调用情况

range(stop=5)# TypeError: range() does not take keyword arguments

range(start=1,stop=5)# 和上边一样

range(5)# range(0, 5)

range(2,5)# range(2, 5)kp和pp的存在(pp是否该出现还在争论中)可以让你的函数设计得更严谨,让调用者更加规范。(当然不当的设计也会带来许多麻烦)(很抱歉暂未解决安卓显示代码超出边界的问题,希望看到完整代码的同学烦请复制链接https://github.com/houluy/wechatpubliccode/blob/master/函数参数有多少.md到浏览器中查看)参考文献:PEP 457: https://www.python.org/dev/peps/pep-0457/PEP 570: https://www.python.org/dev/peps/pep-0570/PEP 3102: https://www.python.org/dev/peps/pep-3102/

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180513G1HQ2M00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券