python编程 从入门到实践 第八章 - 函数
定义函数
函数的定义方式
- 先使用关键字
def
来告诉Python你要定义一个函数。 - 接下来指出函数名称
- 后面的括号内指出函数为完成任务需要输入什么样的信息。(如果什么都不需要则为空,但是括号不可省略)
- 最后用冒号作为结尾
- 紧跟在定义行后面的所有缩进构成了函数体
def function(params):
"""文档字符串(docstring)"""
function body
向函数传递信息
在函数定义时的括号中添加变量,则可以在调用函数的时候向函数传递指定的值。
函数定义中的参数成为形参(函数完成其工作所需的一项信息)
在调用函数中括号里面的内容为实参(调用函数时传递给被调函数的信息)
函数调用的时候,会将实参的值传递给形参
Part One练习
# 8.1 消息
print('---------- 8.1 ----------')
def display_message():
print('What we have learnt in this chapter is function.')
display_message()
#8.2 喜欢的图书
print('---------- 8.2 ----------')
def favourite_book(title):
print('One of my favourite books is',title)
favourite_book('Python')
传递实参
调用函数时,python必须准确将函数调用中的每个实参都关联到函数定义中的一个形参。
位置实参
这种关联方式基于实参的顺序
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')
关键字实参
关键字实参是传递给函数的名称-值对。务必准确指定函数定义中的形参名称。
由于直接在实参中将名称和值关联起来了,因此向函数传递实参时不会混淆,无需考虑函数调用中实参顺序。
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(pet_name='harry', animal_type='hamster')
默认值
编写函数时候,可以给每个形参指定默认值。在调用函数中给形参提供了实参时,python将使用指定的实参值,否则将会使用形参的默认值。
在形参列表中应该先列出没有默认值的形参,然后再列出有默认值的形参,这样可以让python能够正确解读位置实参。
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('harry')
实参错误
实参不匹配错误的报错信息是:
Traceback (most recent call last):
File "E:\xxx\xxx\xxx.py", line 12, in <module>
function()
TypeError: function() missing 1 required positional argument: 'xxx'
由于这里的报错会指出函数调用缺少的实参以及其名称,因此也许无需打开函数文件查看函数代码即可重新正确编写函数调用。
Part Two练习
# 8.3 T恤
print('---------- 8.3 ----------')
def make_shirt(size, word):
print('size:',size,'| word:',word)
make_shirt('small','LOVE')
make_shirt(size='small', word='LOVE')
# 8.4 大号T恤
print('---------- 8.4 ----------')
def make_shirt(size='big', word='I love python.'):
print('size:',size,'| word:',word)
make_shirt()
make_shirt('medium')
make_shirt(word='LOVE')
# 8.5 城市
print('---------- 8.5 ----------')
def describe_city(city, country='China'):
print(city, 'is in', country)
describe_city('Beijing')
describe_city("Xi'an")
describe_city('New York', 'USA')
返回值
返回简单值
函数内部添加一个返回值即可:return xxx
让实参变成可选的
给某可选实参指定一个默认值,并将其移动到形参列表的末尾,如没有对应的实参给其传值,则是默认值。在函数体内对其如果等于默认值则有特殊的操作,以此实现可选实参。
返回字典
与返回简单值原理相似。
结合使用函数和while循环
结合书上示例代码很容易理解。
Part Three练习
# 8.6 城市名
print('---------- 8.6 ----------')
def city_country(city, country):
return city + ', ' + country
print(city_country('Santiago', 'Chile'))
# 8.7 专辑
print('---------- 8.7 ----------')
def make_album(singer, album):
return {'singer':singer, 'album':album}
print(make_album('singer_A', 'album_A'))
def make_album(singer, album, num=-1):
return_dict = {'singer':singer, 'album':album}
if num >= 0:
return_dict['song num'] = num
return return_dict
print(make_album('singer_A', 'album_A'))
print(make_album('singer_A', 'album_A', 10))
# 8.8 用户的专辑
print('---------- 8.8 ----------')
def make_album(singer, album):
return {'singer':singer,'album':album}
while True:
print('Please tell me your information')
print("Enter 'q' at any time to quit")
singer_name = input('Singer name: ')
if singer_name == 'q':
break
album_name = input('Album: ')
if album_name == 'q':
break
user_album = make_album(singer_name, album_name)
print('user album : ', user_album)
传递列表
在函数中修改列表–传递本体
将列表传递给函数之后,函数即可对其进行修改。
禁止函数修改列表–传递副本
可通过向函数传递一个副本来禁止函数修改列表。
function_name(list_name[:])
切片表示法[:]
表示创建列表的副本。
Part Four练习
# 8.9 魔术师
print('---------- 8.9 ----------')
def show_magicians(magicians):
for magician in magicians:
print(magician)
magicians = ['magician_1', 'magician_2', 'magician_3']
show_magicians(magicians)
# 8.10 了不起的魔术师
print('---------- 8.10 ----------')
def show_magicians(magicians):
for magician in magicians:
print(magician)
def make_great(magicians):
for i in range(len(magicians)):
magicians[i] = 'the Great ' + magicians[i]
# 这里如果写成:
#magicians = list('the Great ' + magicians[i] for i in range(len(magicians)))
#print(magicians)
# 函数里面的magicians的值会变化,但是无法传出去。
# 虽然说是引用传递(这个说法不准确),但是相当于magicians指向了其他的一段内存
# 而原本传入实参对应的内存还是没有改变。
magicians = ['magician_1', 'magician_2', 'magician_3']
print('magicians before make great:')
show_magicians(magicians)
make_great(magicians)
print('magicians after make great:')
show_magicians(magicians)
# 8.11 不变的魔术师
print('---------- 8.11 ----------')
def show_magicians(magicians):
for magician in magicians:
print(magician)
def make_great(magicians):
for i in range(len(magicians)):
magicians[i] = 'the Great ' + magicians[i]
return magicians
magicians = ['magician_1', 'magician_2', 'magician_3']
print('magicians before make great:')
show_magicians(magicians)
magicians_great = make_great(magicians[:])
print('magicians after make great:')
show_magicians(magicians)
print('Return value of magicians after make great:')
show_magicians(magicians_great)
传递任意数量的实参
传递任意数量的实参构成的列表
有时预先不知道函数需要接受多少个实参。
def make_pizza(*toppings):
print(toppings)
make_pizza('a')
make_pizza('a', 'b', 'c')
形参名*toppings
中的星号是让python创建一个名字为toppings
的空元组,并将收到的所有值都封装到这元组中。
结合使用位置实参和任意数量的实参
def make_pizza(size, *toppings):
print(toppings)
make_pizza(1, 'a')
make_pizza(3, 'a', 'b', 'c')
使用任意数量的关键字实参
def build_profile(first, last, **user_info):
profile = {}
profile['first_name'] = first
profile['last_name'] = last
for k,v in user_info.items():
profile[k] = v
return profile
user_profile = build_profile('albert', 'einstein',
location="princeton",
field='physics')
print(user_profile)
形参**user_info
中的两个星号让python创建一个名为user_info
的空字典,并将所有名称-值对都封装到这个字典中。
Part Five练习
# 8.12 三明治
print('---------- 8.12 ----------')
def show_toppings(*toppings):
for topping in toppings:
print(topping, end = ' ')
print()
show_toppings('mushrooms')
show_toppings('green peppers','pepperoni','extra cheese')
# 8.13 用户简介
print('---------- 8.13 ----------')
def build_profile(first, last, **user_info):
profile = {}
profile['first_name'] = first
profile['last_name'] = last
for k,v in user_info.items():
profile[k] = v
return profile
user_profile = build_profile('Vera', 'Zhang',
city="Xi'an",
age=24,
language='Chinese')
print(user_profile)
# 8.14 汽车
print('---------- 8.14 ----------')
def make_car(producer, size, **car_info):
info_dict = {}
info_dict['producer'] = producer
info_dict['size'] = size
for k,v in car_info.items():
info_dict[k] = v
return info_dict
car = make_car('subaru', 'outback', color='blue', tow_package=True)
print(car)
将函数存储在模块中
导入整个模块
import module_name
让python打开文件module_name.py
并将其中所有函数都复制到整个程序中。
只需要编写一条import语句并在其中指定模块名,就可以在程序中使用该模块中的所有函数。
如果使用了这种import语句导入了整个模块,则可以通过下面的语法使用其中的任何一个函数:module_name.function_name()
导入特定的函数
from module_name import function_name
通过用逗号分隔函数名,可以根据需要从模块中导入任意数量的函数:
from module_name import function_name1, function_name2, function_name3
如果使用这种语法,则调用函数时无需使用句点。
由于我们在import语句中显式地导入了函数,因此调用时候无需指定其名称。
使用as给函数指定别名
from module_name import function_name as fn
上面的语句将函数function_name ()
重命名为fn()
使用as给模块指定别名
import module_name as mn
导入模块中的所有函数
frommodule_name import *