Crossin的编程教室

标题: 【Python 第69课】函数的参数传递(3) [打印本页]

作者: crossin先生    时间: 2014-5-26 16:30
标题: 【Python 第69课】函数的参数传递(3)


今天来说说最为灵活的一种参数传递方式:

func(**kargs)

上次说的 func(*args) 方式是把参数作为 tuple 传入函数内部。而 func(**kargs) 则是把参数以键值对字典的形式传入。

示例:
def printAll(**kargs):
        for k in kargs:
                print k, ':', kargs[k]

printAll(a=1, b=2, c=3)
printAll(x=4, y=5)

输出:
a : 1
c : 3
b : 2
y : 5
x : 4

字典是无序的,所以在输出的时候,并不一定按照提供参数的顺序。同样在调用时,参数的顺序无所谓,只要对应合适的形参名就可以了。于是,采用这种参数传递的方法,可以不受参数数量、位置的限制。

当然,这还不够。Python 的函数调用方式非常灵活,前面所说的几种参数调用方式,可以混合在一起使用。看下面这个例子:

def func(x, y=5, *a, **b):
   print x, y, a, b

func(1)
func(1,2)
func(1,2,3)
func(1,2,3,4)
func(x=1)
func(x=1,y=1)
func(x=1,y=1,a=1)
func(x=1,y=1,a=1,b=1)
func(1,y=1)
func(1,2,3,4,a=1)
func(1,2,3,4,k=1,t=2,o=3)

输出:
1 5 () {}
1 2 () {}
1 2 (3,) {}
1 2 (3, 4) {}
1 5 () {}
1 1 () {}
1 1 () {'a': 1}
1 1 () {'a': 1, 'b': 1}
1 1 () {}
1 2 (3, 4) {'a': 1}
1 2 (3, 4) {'k': 1, 't': 2, 'o': 3}

在混合使用时,首先要注意函数的写法,必须遵守:
带有默认值的形参(arg=)须在无默认值的形参(arg)之后;
元组参数(*args)须在带有默认值的形参(arg=)之后;
字典参数(**kargs)须在元组参数(*args)之后。

可以省略某种类型的参数,但仍需保证此顺序规则。

调用时也需要遵守:
指定参数名称的参数要在无指定参数名称的参数之后;
不可以重复传递,即按顺序提供某参数之后,又指定名称传递。

而在函数被调用时,参数的传递过程为:
1.按顺序把无指定参数的实参赋值给形参;
2.把指定参数名称(arg=v)的实参赋值给对应的形参;
3.将多余的无指定参数的实参打包成一个 tuple 传递给元组参数(*args);
4.将多余的指定参数名的实参打包成一个 dict 传递给字典参数(**kargs)。

是不是乍一看有点绕?没关系,赶紧打开你的编辑器,自行体会一下不同调用方式的用法。然后在未来的编程实践中慢慢熟悉吧。

作者: jpjlqone    时间: 2014-5-28 11:10
if “sum it up nice” then '@印象笔记'
作者: liu-pengfei    时间: 2014-9-29 23:32
回复赚点积分。
作者: 孙飞    时间: 2014-10-23 14:56
不错,顶一个
作者: chalynn    时间: 2015-1-19 14:13
带有默认值的形参(arg=)须在无默认值的形参(arg)之后;
元组参数(*args)须在带有默认值的形参(arg=)之后;
字典参数(**kargs)须在元组参数(*args)之后。
作者: ngtf    时间: 2015-3-1 09:09
好 继续学习
作者: muneer    时间: 2015-4-14 14:53
赚积分有啥用?
作者: crossin先生    时间: 2015-4-15 13:54
muneer 发表于 2015-4-14 14:53
赚积分有啥用?

没啥用……
下次开一个需要积分浏览的帖子
作者: muneer    时间: 2015-4-15 20:31
crossin先生 发表于 2015-4-15 13:54
没啥用……
下次开一个需要积分浏览的帖子

那还是有用的
作者: 756318887    时间: 2015-10-13 14:22

作者: 草办    时间: 2015-12-15 15:19
get
作者: 我是一个小菜鸟    时间: 2016-1-11 11:10
元组参数(*args)须在带有默认值的形参(arg=)之后;元组参数。。。
作者: dekun    时间: 2016-6-12 09:03
实践一下
作者: Yumiao_HyunMin    时间: 2016-7-1 10:53
涨姿势了~
作者: karlchen    时间: 2016-7-20 11:36
def func(x, y=5, *a, **b):
   print x, y, a, b
func(1,2,3)
func(1,2,3,4)
输出:
1 2 (3,) {}
1 2 (3, 4) {}

为什么(3,)后面有逗号,(3,4)后面没逗号呢


作者: crossin先生    时间: 2016-7-20 12:41
karlchen 发表于 2016-7-20 11:36
def func(x, y=5, *a, **b):
   print x, y, a, b
func(1,2,3)

(3,4)后面的逗号可以省略,但(3,)不行,省略了就不是元组类型了
作者: karlchen    时间: 2016-7-20 14:51
crossin先生 发表于 2016-7-20 12:41
(3,4)后面的逗号可以省略,但(3,)不行,省略了就不是元组类型了

(3)是不是会被python认为是数据公式小括号包裹着3,算出来的其实是一个整数值。所以就不是元祖了呢?
作者: crossin先生    时间: 2016-7-20 16:26
karlchen 发表于 2016-7-20 14:51
(3)是不是会被python认为是数据公式小括号包裹着3,算出来的其实是一个整数值。所以就不是元祖了呢? ...

是,这是个很容易被忽视的bug,我自己都被坑过
作者: karlchen    时间: 2016-7-20 20:10
crossin先生 发表于 2016-7-20 16:26
是,这是个很容易被忽视的bug,我自己都被坑过

谢谢crossin
作者: 妙舞汉宫人    时间: 2016-8-10 16:52
就本题程序,为什么会输出1 1 () {'a': 1}呢
那个{'a': 1}是怎么来的?函数定义中没有啊
作者: crossin先生    时间: 2016-8-11 11:11
妙舞汉宫人 发表于 2016-8-10 16:52
就本题程序,为什么会输出1 1 () {'a': 1}呢
那个{'a': 1}是怎么来的?函数定义中没有啊 ...

传递的时候不是给了 a=1 吗,这个不用定义的,**b就是获取所有未定义的参数字典
作者: kk123456    时间: 2017-2-22 14:56
先生:
有点不理解 func (x=1,y=1,a=1)输出是1 1 () {'a':1}而不是1 1 (1,) {}

作者: crossin先生    时间: 2017-2-22 15:47
kk123456 发表于 2017-2-22 14:56
先生:
有点不理解 func (x=1,y=1,a=1)输出是1 1 () {'a':1}而不是1 1 (1,) {}

* 得到是未指定参数
** 是指定参数

这个和你这里是不是叫a没有关系,你指定了参数名,就是进最后一个字典
作者: kk123456    时间: 2017-2-23 08:45
crossin先生 发表于 2017-2-22 15:47
* 得到是未指定参数
** 是指定参数

明白了,谢谢!!
作者: brahmagupta    时间: 2017-3-4 13:26
无指定参数的实参打包成 tuple。
好吧。
作者: xiejiali    时间: 2018-1-13 07:20
请问第三个为什么是(3,)而不是3呢
作者: crossin先生    时间: 2018-1-13 11:14
xiejiali 发表于 2018-1-13 07:20
请问第三个为什么是(3,)而不是3呢

是元组对象,即使只有一个元素
作者: Frank.Lin    时间: 2018-3-3 15:15
这节课有点绕,既要记住组和字典,还要学习参数的调用,好难记。




欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5