Python编程-第八章-函数

一个简单的函数定义

def greet_user():
    """ Show simple greeting """
    print("Hello!")
greet_user()
# 传入参数
def greet_user(username):
    """ Show simple greeting """
    print(f"Hello, {username.title()}!")
greet_user('Jesse')

8.1.2 实参和形参
在函数greet_user() 的定义中,变量username 是一个形参 (parameter)
在代码greet_user('jesse') 中,值'jesse' 是一个实参 (argument)

练习题

练习8-1:消息 编写一个名为display_message() 的函数,它打印一个句子,指出你在本章学的是什么。调用这个函数,确认显示的消息正确无误。

def display_message():
    print(f"This chapter is learning about functions.")
display_message()

练习8-2:喜欢的图书 编写一个名为favorite_book() 的函数,其中包含一个名为title 的形参。这个函数打印一条消息,下面是一个例子。One of my favorite books is Alice in Wonderland

def favorite_book(title):
    print(f"My favorite books are:{title.title()}")
favorite_book('utopia')

传递实参

# 位置实参
def describe_pet(animal_type,pet_name):
    """Show pet information"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('hamster','harry')
# 关键字实参
def describe_pet(animal_type,pet_name):
    """Show pet information"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet(animal_type='hamster',pet_name='harry')

参数默认值

编写函数时,可给每个形参指定默认值 。

def describe_pet(animal_type='dog',pet_name='alice'):
    """Show pet information"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet(pet_name='whillie')

练习题

练习8-3:T恤 编写一个名为make_shirt() 的函数,它接受一个尺码以及要印到T恤上的字样。这个函数应打印一个句子,概要地说明T恤的尺码和字样。使用位置实参调用该函数来制作一件T恤,再使用关键字实参来调用这个函数

def make_shirt(size,symbol):
    print(f"Make size of {size},print {symbol} printedWords")
make_shirt(size='XXL',symbol='kingbase')
# 添加默认值
def make_shirt(size='XXL',symbol='I love Python'):
    print(f"Make size of {size},print {symbol} printedWords")
make_shirt(size='XXL',symbol='kingbase')
make_shirt()

返回值

def get_formatted_name(first_name,last_name):
    """Returns the neat name. """
    full_name = f"{first_name} {last_name}"
    return full_name.title()
musician = get_formatted_name('jimi','hendrix')
print(musician)

可选参数

def get_formatted_name(first_name,last_name,middle_name=''):
    """Returns the neat name. """
    if middle_name:
        full_name = f"{first_name}  {middle_name} {last_name}"
    else:
        full_name = f"{first_name}  {last_name}"
    return full_name.title()
musician = get_formatted_name('jimi','hendrix')
print(musician)
musician = get_formatted_name('jimi','hoooker','hendrix')
print(musician)

返回字典

def get_formatted_name(first_name,last_name,middle_name=''):
    """Returns the neat name. """
    if middle_name:
        person={'first': first_name,'midll_name': middle_name,'last': last_name}
    else:
        person = {'first': first_name,  'last': last_name}
    return person
musician = get_formatted_name('jimi','hendrix')
print(musician)
musician = get_formatted_name('jimi','hoooker','hendrix')
print(musician)

可选参数配置

def build_person(first_name,last_name,age=None):
    """Returns a dictionary containing information about a person. """
    person = {'first': first_name,'last': last_name}
    """If age has an incoming parameter, it will be assigned. """
    if age:
        person['age']=age
    return person
musician = build_person('jimi','hendrix',age=27)
print(musician)
Warning

和while 循环结合使用函数

def get_formatted_name(first_name,last_name):
    """Returns the neat name. """
    full_name = f"{first_name} {last_name}"
    return full_name.title()
    # This is an infinite loop.
while True:
    print("\nPlease tell me your name:")
    print("\nenter 'q' at any time to quit")

    f_name = input("First name:")
    if f_name == 'q':
        break
    l_name = input("Last name:")
    if l_name == 'q':
        break
    formattted_name =get_formatted_name(f_name,l_name)
    print(f"\nHello, {formattted_name}!")

练习题

练习8-7:专辑 编写一个名为make_album() 的函数,它创建一个描述音乐专辑的字典。这个函数应接受歌手的名字和专辑名,并返回一个包含这两项信息的字典。使用这个函数创建三个表示不同专辑的字典,并打印每个返回的值,以核实字典正确地存储了专辑的信息。

def city_country(city,country):
    message=f"{city},{country}"
    return message
values=city_country('newyork','America')
print(f"\"{values}\"")

练习8-7:专辑 编写一个名为make_album() 的函数,它创建一个描述音乐专辑的字典。这个函数应接受歌手的名字和专辑名,并返回一个包含这两项信息的字典。使用这个函数创建三个表示不同专辑的字典,并打印每个返回的值,以核实字典正确地存储了专辑的信息。
给函数make_album() 添加一个默认值为None 的可选形参,以便存储专辑包含的歌曲数。如果调用这个函数时指定了歌曲数,就将该值添加到表示专辑的字典中。调用这个函数,并至少在一次调用中指定专辑包含的歌曲数

def make_album(name,album_name,numberOfAlbums=None):
    if numberOfAlbums:
        album={'name': name ,'ablum_name': album_name,'number': numberOfAlbums}
    else:
        album={'name': name ,'ablum_name': album_name}
    return  album
current_album=make_album('linkpark','alice')
print(f"{current_album}")
current_album=make_album('linkpark','alice')
print(f"{current_album}")
current_album=make_album('linkpark','alice')
print(f"{current_album}")

current_album=make_album('linkpark','alice','23')
print(f"{current_album}")

练习8-8:用户的专辑 在为完成练习8-7编写的程序中,编写一个while 循环,让用户输入专辑的歌手和名称。获取这些信息后,使用它们来调用函数make_album() 并将创建的字典打印出来。在这个while 循环中,务必提供退出途径。

def make_album(name,album_name,numberOfAlbums=None):
    if numberOfAlbums:
        album={'name': name ,'ablum_name': album_name,'number': numberOfAlbums}
    else:
        album={'name': name ,'ablum_name': album_name}
    return  album
while True:
    print("\nPlease enter an album infomation. ")
    print("\nPlease enter 'q' to exit the program. ")

    p_name = input("name:")
    if p_name == 'q':
        break
    a_name = input("ablum name:")
    if a_name == 'q':
        break
    n_number = input("ablum number:")
    if n_number == 'q':
        break
    ablum = make_album(p_name,a_name,n_number)
    print(f"\nHello,{ablum}!")


传递列表

def greet_users(names):
    """Send a simple greeting to each user on the list. """
    for name in names:
        msg = f"Hello,{name.title()}!"
        print(msg)
usernames=['hannah','ty','margot']
greet_users(usernames)

在函数中修改列表

def print_models(unprinted_designs,completed_models):
# Simulate printing each design until there are no unprinted designs.
# After printing each design, move it to the list completed models.
    while unprinted_designs:
        current_design = unprinted_designs.pop()
        print(f"Printing model: {current_design}")
        completed_models.append(current_design)
# Displays all printed models.
def show_completed_modes(completed_models):
    print("\nThe following modes have been prited:")
    for completed_model in completed_models:
        print(completed_model)

unprinted_designs=['phone case','robot pendant','dodecahedron']
completed_models = []
print_models(unprinted_designs,completed_models)
show_completed_modes(completed_models)

禁止修改列表

切片表示法[:] 创建列表的副本。在printing_models.py中,如果不想清空未打印的设计列表,可像下面这样调用print_models()

# 调用函数时,使用`unprinted_designs[:]`

unprinted_designs=['phone case','robot pendant','dodecahedron']
completed_models = []
print_models(unprinted_designs[:],completed_models)
show_completed_modes(completed_models)

练习题

练习8-9:消息 创建一个列表,其中包含一系列简短的文本消息。将该列表传递给一个名为show_messages() 的函数,这个函数会打印列表中的每条文本消息

def show_messages(msg):
    for msg_values in msg:
        print(f"{msg_values}")
msg =['test','waring','list','history']
show_messages(msg)

练习8-10:发送消息 在你为完成练习8-9而编写的程序中,编写一个名为send_messages() 的函数,将每条消息都打印出来并移到一个名为sent_messages 的列表中。调用函数send_messages() ,再将两个列表都打印出来,确认正确地移动了消息。

def send_messages(unsend_msg,send_msg):
    while unsend_msg:
        current_msg = unsend_msg.pop()
        print(f"send model:{current_msg}")
        send_msg.append(current_msg)
def show_messages(msg):
    for msg_values in msg:
        print(f"{msg_values}")
msg =['test','waring','list','history']

unsend_msg=['alice','fwaring','list','history']
send_msg=[]
send_messages(unsend_msg,send_msg)
show_messages(send_msg)

练习8-11:消息归档 修改你为完成练习8-10而编写的程序,在调用函数send_messages() 时,向它传递消息列表的副本。调用函数send_messages() 后,将两个列表都打印出来,确认保留了原始列表中的消息。

def send_messages(unsend_msg,send_msg):
    while unsend_msg:
        current_msg = unsend_msg.pop()
        print(f"send model:{current_msg}")
        send_msg.append(current_msg)
def show_messages(msg):
    for msg_values in msg:
        print(f"{msg_values}")
msg =['test','waring','list','history']

unsend_msg=['alice','fwaring','list','history']
send_msg=[]
send_messages(unsend_msg[:],send_msg)
show_messages(send_msg)
show_messages(unsend_msg)

传递任意数量的实参

形参名*toppings 中的星号让Python创建一个名为toppings 的空元组

def make_pizza(*toppings):
    """Print all the ingredients ordered by the customer"""
    print(f"\nMaking a pizza with the following toppings:")
    for topping in toppings:
        print(f"- {topping}")

make_pizza('pepperroni')
make_pizza('mushrooms','gree pepperes','extra cheese')

固定数量的实参和任意数量的实参

如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。例如,如果前面的函数还需要一个表示比萨尺寸的形参,必须将其放在形参*toppings 的前面

def make_pizza(size,*toppings):
    """Print all the ingredients ordered by the customer"""
    print(f"\nMaking a{size} pizza with the following toppings:")
    for topping in toppings:
        print(f"- {topping}")

make_pizza(16,'pepperroni')
make_pizza(12,'mushrooms','gree pepperes','extra cheese')

使用任意数量的关键词实参

使用任意数量的关键字实参
形参**user_info 中的两个星号让Python创建一个名为user_info的空字典,

def build_profile(first,last,**user_info):
    """Create a dictionary with all the user's information. """
    user_info['first_name'] = first
    user_info['last_name'] =last
    return user_info
user_profile=build_profile('albert','einstein',locaion='princeton',field='physics')
print(user_profile)

我们调用build_profile() ,向它传递名('albert' )、姓('einstein')和两个键值对(location='princeton' 和field='physics' ),并将返回的user_info 赋给变量user_profile ,再打印该变量:

练习题

练习8-12:三明治 编写一个函数,它接受顾客要在三明治中添加的一系列食材。这个函数只有一个形参(它收集函数调用中提供的所有食材),并打印一条消息,对顾客点的三明治进行概述。调用这个函数三次,每次都提供不同数量的实参

def make_sandwich(*toppings):
    for topping in toppings:
        print(f"- {topping}")
make_sandwich('mushrooms')
make_sandwich('mushrooms','green peppers','extra cheess')

练习8-13:用户简介 复制前面的程序user_profile.py,在其中调用build_profile() 来创建有关你的简介。调用这个函数时,指定你的名和姓,以及三个描述你的键值对

def build_profile(first,last,**user_info):
    """Create a dictionary with all the user's information. """
    user_info['first_name'] = first
    user_info['last_name'] =last
    return user_info
user_profile=build_profile('chen','cheng',locaion='china',field='physics',province='chongqing')
print(user_profile)

练习8-14:汽车 编写一个函数,将一辆汽车的信息存储在字典中。这个函数总是接受制造商和型号,还接受任意数量的关键字实参。这样调用该函数:提供必不可少的信息,以及两个名称值对,如颜色和选装配件。这个函数必须能够像下面这样进行调用

def make_cars(product,modle,**cars_info):
    """Create a dictionary with all the user's information. """
    cars_info['product'] = product
    cars_info['modle'] =modle
    return cars_info
car=make_cars('subaru','outback',color='blue',tow_package='True')
print(car)

将函数存储在模块中

你还可以更进一步,将函数存储在称为模块 的独立文件中,再将模块导入 到主程序中。import 语句允许在当前运行的程序文件中使用模块中的代码。

导入整个模块

要让函数是可导入的,得先创建模块。模块 是扩展名为.py的文件,包含要导入到程序中的代码。下面来创建一个包含函数make_pizza() 的模块。为此,将文件pizza.py中除函数make_pizza() 之外的其他代码删除

def make_pizza(size,*toppings):
    """Outline the pizza to be made. """
    print((f"\nMaking a {size}-inch pizza with the following topping:"))
    for topping in toppings:
        print(f"-{topping}")

接下来,在pizza.py所在的目录中创建一个名为making_pizzas.py的文件。这个文件导入刚创建的模块,再调用make_pizza() 两次

import pizza
pizza.make_pizza(16,'pepperoni')
pizza.make_pizza(16,'pepperoni','mushrooms','green peppers','extra cheese')
Note

import 操作是将对应的模块里面的内容加入到当前代码里 。

导入特定的函数

from pizza import  make_pizza
make_pizza(16,'pepperoni')
make_pizza(16,'pepperoni','mushrooms','green peppers','extra cheese')

Warning

如果只导入函数,可以使用上面的语法。
如果只导入函数,则可以省略模块名称。

使用AS 给函数别名

如果要导入函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名 :函数的另一个名称,类似于外号。要给函数取这种特殊外号,需要在导入它时指定

from pizza import  make_pizza as mp
mp(16,'pepperoni')
mp(16,'pepperoni','mushrooms','green peppers','extra cheese')

使用AS 给模块指定别名

import pizza as p
p.make_pizza(16,'pepperoni')
p.make_pizza(16,'pepperoni','mushrooms','green peppers','extra cheese')

导入模块中的所有函数

from pizza import * 
# import pizza as p
make_pizza(16,'pepperoni')
make_pizza(16,'pepperoni','mushrooms','green peppers','extra cheese')

Warning

导入模块中的所有函数,这样就可以不用写模块名称。
但是要注意,为了代码更加容易阅读,最好只导入需要的函数名称。

函数编写指南

1、应给函数指定描述性名称,且只在其中使用小写字母和下划线。
2、每个函数都应包含简要地阐述其功能的注释。该注释应紧跟在函数定义后面,并采用文档字符串格式。
3、给形参指定默认值时,等号两边不要有空格:

def function_name(parameter_0, parameter_1='default value')

4、PEP 8建议代码行的长度不要超过79字符,这样只要编辑器窗口适中,就能看到整行代码。如果形参很多,导致函数定义的长度超过了79字符,可在函数定义中输入左括号后按回车键,并在下一行按两次Tab键,从而将形参列表和只缩进一层的函数体区分开来。大多数编辑器会自动对齐后续参数列表行,使其缩进程度与你给第一个参数列表行指定的缩进程度相同:

def function_name(         
				  parameter_0, parameter_1, parameter_2,         
				  parameter_3, parameter_4, parameter_5):

练习题

练习8-15:打印模型 将示例printing_models.py中的函数放在一个名为printing_functions.py的文件中。在printing_models.py的开头编写一条import 语句,并修改该文件以使用导入的函数。

练习8-16:导入 选择一个你编写的且只包含一个函数的程序,将该函数放在另一个文件中。在主程序文件中,使用下述各种方法导入这个函数,再调用它:

from printing_function  import print_models
from printing_function  import show_completed_modes

unprinted_designs=['phone case','robot pendant','dodecahedron']
completed_models = []
print_models(unprinted_designs,completed_models)
show_completed_modes(completed_models)