前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Python】8“函数的参数“

【Python】8“函数的参数“

作者头像
肓己
发布2021-08-12 10:24:56
3580
发布2021-08-12 10:24:56
举报
文章被收录于专栏:linux commands

位置参数

按函数参数顺序传入参数,这样的参数就叫做位置参数。Java的函数中,规定调用者必须按形式参数顺序依次传入参数,这样也可以看做是位置。 案例(幂运算):

代码语言:javascript
复制
>>> def power(x,n):
...     s = 1
...     while n > 0:
...             n = n - 1
...             s = s * x
...     return s
... 
>>> power(2,4)
16

默认参数

在定义函数的时候,可以定义默认参数,也就是参数含有默认值。 案例(info):

代码语言:javascript
复制
>>> def info(name,age,gender,city = 'guangzhou'):
...     print(name,age,gender,city)
... 
>>> info('张三',20,'male')
张三 20 male guangzhou

要注意的是,默认参数要放在函数形参最后的位置,这样能让调用者在调用函数时传入的值是必须传入的参数。 应用场景:比如需要一批数据,而数据的某一项的内容大部分都是相同的,这样就可以使用默认参数在定义这项内容,能提高调用的效率。

默认参数坑 △默认参数必须指向不可变对象!

代码语言:javascript
复制
>>> def add_end(L= []):
...     L.append('END')
...     return L
>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']

因为list是可变对象,L指向的对象在函数定义时的内容是[],在调用后,函数往L所指向的对象[]append'END',这时[]就变成['END'],下次再调用时,就在这个对象的基础上append,所以就成了上面的运行情况。 解决:

代码语言:javascript
复制
>>> def add_end(L = None):
...     if L is None:
...             L = []
...     L.append('END')
...     return L
... 
>>> add_end()
['END']
>>> add_end()
['END']
>>> add_end()
['END']

因为None是不可变对象,所以使用None能解决这个坑。

为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

可变参数

也就是说传入的参数是可变的,比如函数需要传入一个list。 案例(calc):

常规方法:需要先组一个list或者tuple,然后传入函数

代码语言:javascript
复制
>>> def calc(numbers):
...     sum = 0
...     for n in numbers:
...             sum = sum + n * n
...     return sum
... 
>>> calc([1,2,3])
14
>>> list = [1,2,3]
>>> calc(list)
14

定义可变参数方法:将N个参数直接传入

代码语言:javascript
复制
>>> def calc(*numbers):
...     sum = 0
...     for n in numbers:
...             sum = sum + n * n
...     return sum
... 
>>> calc(1,2,3)
14
>>> calc(2,4,6,8)
120

如果需要传入list或者tuple:在list或者tuple前面加上*

代码语言:javascript
复制
>>> list = [1,2,3]
>>> calc(*list)
14

*list表示把list这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。

关键字参数

关键字参数允许调用者传入0个或者任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。

这句话有点拗口,一开始我并不理解‘含参数名的参数’,但通过代码,可以简单明了地理解:

代码语言:javascript
复制
>>> def person(name,age,**kw):
...     print('name:', name, 'age:', age, 'other:', kw)
... 
>>> person('张三',20)
name: 张三 age: 20 other: {}
>>> person('张三',20,gender = 'male')
name: 张三 age: 20 other: {'gender': 'male'}
>>> person('张三',20,gender = 'male',city = 'guangzhou',hight = 175)
name: 张三 age: 20 other: {'gender': 'male', 'city': 'guangzhou', 'hight': 175}

其实就是让调用者传入带参数名的参数,这样做能让函数更具有拓展性。比如在上面这个代码案例中,姓名和年龄是必传属性,而函数定义的**kw就是关键字参数,能让调用者传入一些额外的信息。 也可以将dict传入:

代码语言:javascript
复制
>>> extra = {'gender':'male','city':'guangzhou'}
>>> person('李四',21,**extra)
name: 李四 age: 21 other: {'gender': 'male', 'city': 'guangzhou'}

**extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra

命名关键字参数

命名关键字可以检查调用者传入的从参数是否有指定的参数。

代码语言:javascript
复制
>>> def person(name,age,*,city,job):
...     print(name,age,city,job)
... 

在定义参数时,命名关键字要使用*符号分隔开,表示*后面的参数都是命名关键字。 在调用时,调用者必须传入cityjob关键字参数,否则会报错:

代码语言:javascript
复制
>>> person('张三',34,city = 'guangzhou',job = 'monkey')
张三 34 guangzhou monkey

△如果函数定义中已经有一个可变参数,那么就不需要*分隔命名关键字了:

代码语言:javascript
复制
>>> def person(name,age,*args,city,job):
...     print(name, age, args, city, job)
... 
>>> args = ['1','2','3']
>>> >>> person('张三','34',args,city = 'guangzhou',job = 'monkey')
张三 34 (['1', '2', '3'],) guangzhou monkey
>>> person('张三','34',city = 'guangzhou',job = 'monkey')
张三 34 () guangzhou monkey

△命名关键字也可以有默认值(缺省值),在函数定义的时候可以设置默认值:

代码语言:javascript
复制
>>> def person(name,age,*,city = 'guangzhou',job):
...     print(name, age, city, job )
... 
>>> person('jack',23,job = 'monkey')
jack 23 guangzhou monkey

参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

我们先来定义两个函数,它们的参数不止一种:

代码语言:javascript
复制
>>> def f1(a,b,c=1,*args,**kw):
...     print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
... 
>>> def f2(a, b, c=0, *, d, **kw):
...     print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
...

我们可以用多种符合python语法形式的参数传入调用:

代码语言:javascript
复制
#调用f1
>>> f1(1,2)
a = 1 b = 2 c = 1 args = () kw = {}
>>> f1(1,2,3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1,2,3,[1,2,3])
a = 1 b = 2 c = 3 args = ([1, 2, 3],) kw = {}
>>> f1(1,2,3,[1,2,3],num1 = 1,num2 = 2)
a = 1 b = 2 c = 3 args = ([1, 2, 3],) kw = {'num1': 1, 'num2': 2}
#调用f2
>>> f2(1,2,d = 3,num1 = 1,num2 = 2)
a = 1 b = 2 c = 0 d = 3 kw = {'num1': 1, 'num2': 2}
>>> f2(1,2,d = 3)
a = 1 b = 2 c = 0 d = 3 kw = {}

△调用f2的时候,我产生一个疑惑,命名关键字参数*后面的参数是必须要传入的,不传入就会报错,这一点已经证实过。 我尝试没有传入**kw的值,发现并没有报错,这样就说明,*分隔命名关键字的同时,不包含python定义参数顺序的后面的参数类型,所以d是命名关键字参数,**kw是关键字参数 参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数

func(*args, **kw)写法

△对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

代码语言:javascript
复制
>>> def func(*args,**kw):
...     print(args)
...     print(kw)
... 
>>> func(a = 1,b = 2)
()
{'a': 1, 'b': 2}
>>> func(1,2,3)
(1, 2, 3)
{}
>>> func(1,2,3,a = 1,b = 2)
(1, 2, 3)
{'a': 1, 'b': 2}

使用*args**kw是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/06/06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 位置参数
  • 默认参数
  • 可变参数
  • 关键字参数
  • 命名关键字参数
  • 参数组合
  • func(*args, **kw)写法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档