位置参数和关键字参数
2009年01月2日 原创
如果在调用函数时,参数的位置决定参数的值,那么这种参数就是位置参数;如果参数的名称(关键字)决定参数的值,则这种参数就是关键字参数。例如,定义下面两个函数:
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, world!
>>> hello_2(‘Hello’, ‘world’)
Hello, world!
由此可以看出参数的名称并不重要,重要的参数的位置。但有时候,在参数较多时,记住参数位置比较困难。这时,就可以在传递参数(实参)时,使用定义时使用的参数(形参)名。例如:
>>> hello_1(greeting=’Hello’, name=’world’)
Hello, world!
而且,此时参数的位置已经不重要了:
>>> hello_1( name=’world’,greeting=’Hello’)
Hello, world! # 结果仍然相同。
但是,参数的名称却很重要:
>>> hello_2(greeting=’Hello’, name=’world’)
world, Hello!
关键字参数最大的好处,就是能够清楚地知道每个参数的角色。比如,单纯看下面这个函数调用:
>>> store(‘Mr. Brainsample’, 10, 20, 13, 5)
如果不知道函数定义,恐怕除编写这行代码的人之外,谁也搞不清传递的这5个参数各自有什么用途,表示什么意思。如果使用关键字参数的话,问题就简单多了:
>>> store(patient=’Mr. Brainsample’, hour=10, minute=20, day=13, month=5)
当然,使用位置参数可以减少一些输入量,使用关键字参数的输入量要多一些。也可以说它们各有所长。但是,令关键字参数更具竞争优势的,则是可以通过它在定义函数时设置参数的默认值。例如:
def hello_3(greeting=’Hello’, name=’world’): print ‘%s, %s!’ % (greeting, name)
如果使用关键字参数设置了参数的默认值,那么调用函数时,可以不提供参数、只提供部分参数,或者提供全部参数:
>>> hello_3()
Hello, world!
>>> hello_3(‘Greetings’)
Greetings, world!
>>> hello_3(‘Greetings’, ‘universe’)
Greetings, universe!
啰嗦一点:位置参数和关键字参数可以组合使用,而唯一的要求就是位置参数必须出现在前面。混合使用位置和关键字参数的情形,通常是要求用户提供少量强制性参数和较多带默认值的可选参数的情形。例如,如果上面的hello函数要求用户必须提供一个名字(name),而问候语(greeting)和标点符号(punctuation)都是可选的,则可以这样来定义:
def hello_4(name, greeting=’Hello’, punctuation=’!'): print ‘%s, %s%s’ % (greeting, name, punctuation)
调用这个函数的方式有很多:
>>> hello_4(‘Mars’)
Hello, Mars!
>>> hello_4(‘Mars’, ‘Howdy’)
Howdy, Mars!
>>> hello_4(‘Mars’, ‘Howdy’, ‘…’)
Howdy, Mars…
>>> hello_4(‘Mars’, punctuation=’.')
Hello, Mars.
>>> hello_4(‘Mars’, greeting=’Top of the morning to ya’)
Top of the morning to ya, Mars!
>>> hello_4()
Traceback (most recent call last):
File “<pyshell#64>”, line 1, in ?
hello_4()
TypeError: hello_4() takes at least 1 argument (0 given)
如果函数定义中也为name指定默认值的话,最后一次调用就不会报错了。
本博客专注于Web前后端技术和技术翻译。目前正在翻译《JavaScript高级程序设计(第2版)》。新浪微博(t.sina.com.cn/lisf),Twitter(@cncuckoo,仅仅用于跟踪国外牛人;我翻不了墙,无法接受各位朋友的follow,抱歉!)