函数关键字参数和默认值

函数关键字参数和默认值

目前为止我们所使用的参数都叫做位置参数,因为它们的位置很重要,事实上比它们的名字更加重要
。本次引入的这个功能可以回避位置问题,当你慢慢习惯使用这个功能以后,就会发现程序规模越大
,它们的作用也就越大。
考虑下面两个函数:


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 Files\python.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 Files\python.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 Files\python.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 Files\python.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 Files\python.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 Files\python.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 Files\python.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 Files\python.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 Files\python.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 Files\python.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 Files\python.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 Files\python.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中两处
都没有用,但是得到同样的效果。所以星号只在定义函数或者调用时才有用。

posted @ 2017-07-02 23:05  Sun珊珊来迟  阅读(377)  评论(0编辑  收藏  举报