函数关键字参数和默认值
目前为止我们所使用的参数都叫做位置参数,因为它们的位置很重要,事实上比它们的名字更加重要
。本次引入的这个功能可以回避位置问题,当你慢慢习惯使用这个功能以后,就会发现程序规模越大
,它们的作用也就越大。
考虑下面两个函数:
def hello_1(greeting,name) :
print("%s,%s!"%(greeting,name))
def hello_2(name,greeting):
print("%s,%s!"%(name,greeting))
两个代码所实现的是完全一样的功能,只是参数顺序反过来了:
hello_1("hello","world")
hello_2("hello","world")
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
hello,world!
hello,world!
Process finished with exit code 0
有些时候(尤其是参数很多的时候),参数的顺序是很难记住的。为了让事情简单些,可以提供参数的
名字:
hello_1(greeting="hello",name="world")
hello_2(name="hello",greeting="world")
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
hello,world!
hello,world!
Process finished with exit code 0
这样一来,顺序就完全没影响了,但参数名和值一定要对应
这类使用参数名提供的参数叫做关键字参数。它的主要作用在于可以明确每个参数的作用,也就避免
了下面这样奇怪的函数调用:
stor("hunny",1,2,3,4)
可以使用:
store(patient="hunny",hour=1,minute=2,day=3,month=4)
尽管这么做打的字就多了些,但是很显然,每个参数的含义就变得更加清晰。而且就算弄乱了参数的
顺序,对于程序的功能没有任何影响。
def hello_1(greeting="hello",name="world"):
print("%s,%s!"%(greeting,name))
hello_1()
hello_1("greeting")
hello_1("greeting","universe")
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
hello,world!
greeting,world!
greeting,universe!
Process finished with exit code 0
同时位置参数和关键字参数是可以联合使用的。把位置参数放置在前面就可以了。如果不这样做解释器
就不知道它们到底是谁了:例
def hello_3(name,greeting="hello",punctuation="!"):
print("%s,%s%s"%(greeting,name,punctuation))
hello_3("many")
hello_3("greeting","howdy")
hello_3("Mars","howdy","....")
hello_3("Mars",punctuation=".")
hello_3("Mars",greeting="Top of the morning to ya")
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
hello,many!
howdy,greeting!
howdy,Mars....
hello,Mars.
Top of the morning to ya,Mars!
Process finished with exit code 0
这样就很灵活了我们也不需要做多少工作
收集参数
有些时候让用户提供任意数量的参数是很有用的。比如在名字存储程序中,用户每次只能存储
一个名字。如果能像下面这样存储多个名字就更好了:
store(data,name1,name2,name3)
用户可以给函数提供任意多的参数。实现起来也不难。例:
def print_params(*params):
print(params)
print_params("huxiaoshan")
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
('huxiaoshan',)
Process finished with exit code 0
从结果中可以看出打印出的是元祖的类型,因为里面有个逗号(长度为1的元祖会出现这个情况)。
所以在参数前使用*号就能打印出元祖?那么在params中使用多个参数看看会发生什么:
def print_params(*params):
print(params)
print_params(1,2,3,)
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
(1, 2, 3)
Process finished with exit code 0
参数前的星号将所有值放置在同一个元祖中。可以说是将这些值收集起来,然后使用。
def print_params(titel,*params):
print(titel)
print(params)
print_params("params:",1,2,3,)
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
params:
(1, 2, 3)
Process finished with exit code 0
从上述可知*号的意思就是“收集其余的位置参数”。如果不提供任何供收集的元素,params就是个
空元祖:
def print_params(titel,*params):
print(titel)
print(params)
print_params("params:")
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
params:
()
Process finished with exit code 0
这里需要了解的是对于关键字参数*号是不能处理的,这里需要用到两个星号进行处理例:
def print_params3(**params):
print(params)
print_params3(x=1,y=2,z=3)
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
{'x': 1, 'y': 2, 'z': 3}
Process finished with exit code 0
返回的类型是字典的类型,现在我们把两者结合在一起使用:
def print_params3(x,y,z=3,*pospar,**keypar):
print(x,y,z)
print(pospar)
print(keypar)
print_params3(1,2,3,4,5,6,7,foo=1,bar=2)
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
1 2 3
(4, 5, 6, 7)
{'foo': 1, 'bar': 2}
Process finished with exit code 0
参数收集的逆过程
如何将参数收集为元祖和字典已经讨论过了,但事实上,如果使用单星号和双星号的话,也可以
执行相反的操作。那么参数收集的逆过程是什么样:
def add(x,y):
return x+y
params=(1,2)
print(add(*params))
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
3
Process finished with exit code 0
对于参数列表来说工作正常,只要扩展的部分是最新的就可以。可以使用同样的计术来处理字典
————使用双星号运算符。
def with_stars(**kwds):
print(kwds["name"],"is" ,kwds["age"],"years old")
def without_starts(kwds):
print("kwds[name],is,kwds[age],years old")
args={"name":"huxiaoshan","age":18}
print(with_stars(**args))
print(without_starts(args))
"D:Program Filespython.exe" "E:/py_code/day 3/while.py"
huxiaoshan is 18 years old
None
kwds[name],is,kwds[age],years old
None
Process finished with exit code 0
可以看到,在with_starts中,我在定义和调用函数时都使用了星号。而在without_starts中两处
都没有用,但是得到同样的效果。所以星号只在定义函数或者调用时才有用。