[TOC]
*****
# 8.1 定义函数
```
#定义函数
def greet_user(username):
"""Display a simple greeting."""
print("Hello, " + username.title() + "!")
#函数调用 给函数传递参数
greet_user('jesse')
```
#8.1.2 实参和形参
在函数greet_user()的定义中,变量username是一个形参 —— 函数完成其工作所需的一项信息。在代码greet_user('jesse')中,值'jesse'是一个实参。
# 8.2 传递实参
## 8.2.1 位置实参
将函数调用中的每个实参都关联到函数定义中的一个形参。 为此,最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参
```
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('hamster', 'harry')
```
2. 位置实参的顺序很重要
```
#这样子编程动物类型是harry, 宠物名字是松鼠,和目标不一致错误
describe_pet('harry', 'hamster')
```
## 8.2.2 关键字实参
关键字实参是传递给函数的名称—值对。你直接在实参中将名称和值关联起来了,因此向函数传递实参时不会混淆(不会得到名为Hamster的harry这样的结果)。关键字实参让你无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。
```
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(animal_type='hamster', pet_name='harry')
```
## 8.2.3 默认值
编写函数时,可给每个形参指定默认值。在调用函数中给默认的形参提供了实参时,使用指定的实参值;否则,将使用形参的默认值。给形参指定默认值后,可在函数调用中省略相应的实参。
```
def describe_pet(pet_name, animal_type='dog'):
"""显示宠物的信息"""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(pet_name='willie')
```
形参是默认值,传参数时实参和形参绑定依然会按照位置绑定
** 注意**
使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的形参。
## 8.2.4 等效的函数调用
对于以下函数定义
```
def describe_pet(pet_name, animal_type='dog'):
```
有几种等效的函数调用
```
# 一条名为Willie的小狗
describe_pet('willie')
describe_pet(pet_name='willie')
# 一只名为Harry的仓鼠
describe_pet ('harry', 'hamster')
describe_pet (pet_name='harry', animal_type='hamster')
describe_pet(animal_type='hamster', pet_name='harry')
```
## 8.2.5 避免实参错误
![](https://img.kancloud.cn/ad/a4/ada4e00828beaceadc36f8269d858d02_414x210.png)
# 8.3 返回值
## 8.3.1 返回简单值
```
def get_formatted_name(first_name, last_name):
"""返回整洁的姓名"""
full_name = first_name + ' ' + last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
```
## 8.3.2 让实参变成可选的
给函数的形参指定默认值为空。不用该参数时不传值。使用参数时,给实参赋值覆盖原来的默认值
```
def get_formatted_name(first_name, last_name, middle_name=''):
musician = get_formatted_name('john', 'hooker', 'lee')
```
## 8.3.3 返回字典
```
def build_person(first_name, last_name, age=''):
"""Return a dictionary of information about a person."""
person = {'first': first_name, 'last': last_name}
return person
```
# 8.4 传递列表
```
def greet_users(names):
"""Print a simple greeting to each user in the list."""
for name in names:
msg = "Hello, " + name.title() + "!"
print(msg)
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)
```
## 8.4.1 在函数中修改列表
将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永
久性的,这让你能够高效地处理大量的数据。
## 8.4.2 禁止函数修改列表
可向函数传递列表的副本而不是原件;这样函数所做的任何修改都只影响副本,而丝毫不影响原件。
```
function_name(list_name[:])
```
# 8.5 传递任意数量的实参
Python允许函数从调用语句中收集任意数量的实参。
```
def make_pizza(*toppings):
"""打印顾客点的所有配料"""
print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
```
形参名*toppings中的星号让Python创建一个名为toppings的空元组,并将收到的所有值都封装到这个元组中
## 8.5.1 结合使用位置实参和任意数量实参
如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最
后。 Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。
例如,如果前面的函数还需要一个表示比萨尺寸的实参,必须将该形参放在形参*toppings的前面:
```
def make_pizza(size, *toppings):
"""概述要制作的比萨"""
print("\nMaking a " + str(size) +
"-inch pizza with the following toppings:")
for topping in toppings:
print("- " + topping)
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
```
Python将收到的第一个值存储在形参size中,并将其他的所有值都存储在元组toppings中。
## 8.5.2 使用任意数量的关键字实参
需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种
情况下,可将函数编写成能够接受任意数量的键—值对——调用语句提供了多少就接受多少。一
个这样的示例是创建用户简介:你知道你将收到有关用户的信息,但不确定会是什么样的信息。
在下面的示例中,函数build_profile()接受名和姓,同时还接受任意数量的关键字实参
```
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('albert', 'einstein', location='princeton', field='physics')
print(user_profile)
```
函数build_profile()的定义要求提供名和姓,同时允许用户根据需要提供任意数量的名称—
值对。形参**user_info中的两个星号让Python创建一个名为user_info的空字典,并将收到的所
有名称—值对都封装到这个字典中。在这个函数中,可以像访问其他字典那样访问user_info中的
名称—值对。
# 8.6 将函数存储在模块中
将函数存储在被称为模块的独立文件中,再将模块导入到主程序中。 import语句允许在当前运行的程序文件中使用模块中的代码。
通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上。 这还能让你在众多不同的程序中重用函数。将函数存储在独立文件中后,可与其他程序员共享这些文件而不是整个程序。知道如何导入函数还能让你使用其他程序员编写的函数库。
## 8.6.1 导入整个模块
要让函数是可导入的,得先创建模块。 模块是扩展名为.py的文件,包含要导入到程序中的代码。
**pizza.py**
```
def make_pizza(size, *toppings):
"""Summarize the pizza we are about to make."""
print("\nMaking a " + str(size) +
"-inch pizza with the following toppings:")
for topping in toppings:
print("- " + topping)
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
```
**making_pizzas.py**
```
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
```
代码行import pizza让Python打开文件pizza.py,并将其中的所有函数都复制到这个程序中。你看不到复制的代码,因为这个程序运行时, Python在幕后复制这些代码。
## 8.6.2 导入特定的函数
**语法** : from module_name import function_name
```
from pizza import make_pizza
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
```
## 8.6.3 使用 as 给函数指定别名
如果要导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名——函数的另一个名称
给函数make_pizza()指定了别名mp()
```
from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')
```
## 8.6.4 使用 as 给模块指定别名
还可以给模块指定别名。通过给模块指定简短的别名(如给模块pizza指定别名p),让你能够更轻松地调用模块中的函数
```
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
```
## 8.6.5 导入模块中的所有函数
使用星号(*)运算符可让Python导入模块中的所有函数:
```
from pizza import *
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
```
不推荐这种做法,要么只导入你需要使用的函数,要么导入整个模块并使用句点表示法
# 8.7 函数编写指南
![](https://img.kancloud.cn/ad/a4/ada4e00828beaceadc36f8269d858d02_414x210.png)
用两个空行将相邻的函数分开