定义函数
一个简单的例子:
def greet_user(username):
print("Hello! " + username.title() + "!")
greet_user('jesse')
可在函数定义def greet_user()的括号内添加username。通过在这里添加username, 就可让函数接受你给username指定的任何值。代码greet_user('jesse')调用函数greet_user(),并向它提供执行print语句所需的信息。
变量username是一个形参---函数完成其工作所需的一项信息。而'jesse'是一个实参,实参是调用函数时传递给函数的信息。调用函数时,将要让函数使用的信息放在括号内。在greet_user('jesse')中,将实参 'jesse'传递给了函数greet_user(),这个值被存储在形参username中。
传递实参
鉴于函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。向函数传递实参 的方式很多,可使用位置实参,这要求实参的顺序与形参的顺序相同;也可使用关键字实参,其 中每个实参都由变量名和值组成;还可使用列表和字典。
位置实参
简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参。 即按函数提供的形参顺序,提供实参。
一个例子:
def describe_pet(animal_type, pet_name):
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet('dog', 'Mike')
describe_pet('Mike', 'dog')#顺序错误,结果不同
关键字实参
关键字实参是传递给函数的名称—值对。直接在实参中将名称和值关联起来了,因此向函 数传递实参时不会混淆:
describe_pet(pet_name = "Mike", animal_type = "dog")
使用关键字实参时,务必准确地指定函数定义中的形参名
默认值
编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时,Python将使用 指定的实参值;否则,将使用形参的默认值。
def describe_pet(pet_name, animal_type = 'dog'):
'''blablablablabla'''
describe_pet(pet_name='Mike')
describe_pet('John', 'cat')
使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的形参。即带有默认值的形参应该放在参数列表最后。 这让Python依然能够正确地解读位置实参。
返回值
在函数中,使用return语句将值返回到调用函数的代码行。。返回值让你能 够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。
一个例子:
def get_formatted_name(first_name, last_name, middle_name=''):
if middle_name:
full_name = first_name + ' ' + middle_name + ' ' + last_name
else:
full_name = first_name + ' ' + last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
上例中,检查是否提供中间名,python将非空字符解读为True,将空字符解读为False。返回值还可以返回列表、字典等类型。
例如:
def build_person(first_name, last_name, age=''):
person = {'first': first_name, 'last': last_name}
if age:
person['age'] = age
return person
musician = build_person('jimi', 'hendrix', age=27)
传递列表
一个例子:
def greet_users(names):
for name in names:
msg = "Hello, " + name.title() + "!"
print(msg)
usernames = ['hannah', 'try', 'margot']
greet_users(usernames)
将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永 久性的,这让你能够高效地处理大量的数据。
def print_models(unprinted_designs, completed_models):
while unprinted_designs:
current_design = unprinted_designs.pop()
print("Printing model: " + current_design)
completed_models.append(current_design)
def show_completed_models(completed_models):
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models=[]
print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)
尽量使每个函数都应只负责一项具体的工作。
为了避免在函数中修改原列表,可向函数传递列表的副本而不是原件;这样函数所做的任何修改都只影响副本,而丝毫不影响原件。
function_name(list_name[:])
虽然向函数传递列表的副本可保留原始列表的内容,但除非有充分的理由需要传递副本,否则还是应该将原始列表传递给函数,因为让函数使用现成列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。
传递任意数量的实参
一个例子:
def make_pizza(size, *toppings):
print("\nMaking a " + str(size) + "-inch pizza with the following toppings: ")
for topping in toppings:
print("- " + topping)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在后。Python先匹配位置实参和关键字实参,再将余下的实参都收集到后一个形参中。
形参名*toppings中的星号让Python创建一个名为toppings的空元组,并将收到的所有值都封 装到这个元组中。
有时候,需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种情况下,可将函数编写成能够接受任意数量的键—值对——调用语句提供了多少就接受多少。
一个例子:
def build_profile(first, last, **user_info):
profile = {}
profile['first_name'] = first
profile['last_name'] = last
for key, value in user_info.items():
profile[key] = value
return profile
user_profile = build_profile('alber', 'einstein', location='princeton', field='physics')
print(user_profile)
形参**user_info中的两个星号让Python创建一个名为user_info的空字典,并将收到的所 有名称—值对都封装到这个字典中。
将函数存储在模块中
函数的优点之一是,使用它们可将代码块与主程序分离。通过给函数指定描述性名称,可让 主程序容易理解得多。将函数存储在被称为模块的独立文件中,再将模块导 入到主程序中。其中,需要将要导入的模块与程序放在同一个文件夹中。import语句允许在当前运行的程序文件中使用模块中的代码。
- 通过 import module_name 来导入模块,通过module_name.function_name()来调用模块中的函数。
- 通过 from module_name import function_name0,function_name1...来从模块中导入指定的函数,可以直接通过function_name0来调用。
- 如果要导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短 而独一无二的别名——函数的另一个名称,类似于外号。如from module_name import function_name as fn
- 给模块起别名,import module_name as m
- 从模块中导入全部函数,from module_name import *,。由于导入 了每个函数,可通过名称来调用每个函数,而无需使用句点表示法。然而,使用并非自己编写的 大型模块时,好不要采用这种导入方法:如果模块中有函数的名称与你的项目中使用的名称相 同,可能导致意想不到的结果:Python可能遇到多个名称相同的函数或变量,进而覆盖函数,而不是分别导入所有的函数。
对于自己的函数,可以加入 '''注释''' 的方法便于理解,同时可以在console中通过function_name.doc的方式查看自己留下的注释,或者查看其他人函数中的注释。
在本章中,你学习了:如何编写函数,以及如何传递实参,让函数能够访问完成其工作所需 的信息;如何使用位置实参和关键字实参,以及如何接受任意数量的实参;显示输出的函数和返 回值的函数;如何将函数同列表、字典、if语句和while循环结合起来使用。你还知道了如何将 函数存储在被称为模块的独立文件中,让程序文件更简单、更易于理解。后,你学习了函数编 写指南,遵循这些指南可让程序始终结构良好,并对你和其他人来说易于阅读。