Python编程 从入门到实践 第八章 函数

1. 定义函数

  1. 函数是带名字的代码块,用于完成具体的工作
  2. 通过使用函数,程序的编写、阅读、测试和修复都将更容易
  3. 演示示例如下:
def greet_user():          #这一行是函数定义,
    """显示简单的问候语"""  #这一行是函数体内:文档字符串的注释,描述函数是干什么的,用三引号括起
    print("Hello!")        #这一行是函数体内:代码

greet_user()               #调用函数
Hello!

1.1 向函数传递信息

  1. 函数定义 ()内可以添加函数为完成任务所需的信息
  2. 演示示例如下:
def greet_user(username):
    """显示简单的问候语"""
    print("Hello," + username.title() + "!")
    
greet_user('jesse')
Hello,Jesse!

1.2 实参和形参

  1. 上面示例中,username 是一个形参,‘jesse’ 是一个实参
  2. 形参:函数完成其工作所需的一项信息
  3. 实参:调用函数时传递给函数的信息

2. 传递实参

  1. 函数定义中可能包含多个形参,函数调用中也可能包含多个实参
  2. 向函数传递实参的方式:位置实参、关键字实参、使用列表和字典

2.1 位置实参

  1. 每个实参按顺序关联到函数定义中的形参,一一对应
  2. 演示示例如下:
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')
describe_pet('dog','willie')
I have a hamster.
My hamster's name is Harry.

I have a dog.
My dog's name is Willie.
  1. 若实参顺序不对,程序运行不报错,但输出结果有逻辑错误
  2. 演示示例如下:
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('harry','hamster')
describe_pet('willie','dog')
I have a harry.
My harry's name is Hamster.

I have a willie.
My willie's name is Dog.

2.2 关键字实参

  1. 关键子实参是传递给函数的名称-值对
  2. 关键字实参无需考虑函数调用中的实参顺序
  3. 演示示例如下:
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')
describe_pet(pet_name='harry',animal_type='hamster')
I have a hamster.
My hamster's name is Harry.

I have a hamster.
My hamster's name is Harry.

2.3 默认值

  1. 编写函数时,可以给每个形参指定默认值
  2. 调用函数时,如果显示的提供了实参就按实参来,没有提供就按照形参的默认值来
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')
describe_pet(pet_name='harry',animal_type='hamster')
I have a dog.
My dog's name is Willie.

I have a hamster.
My hamster's name is Harry.
  1. 使用默认值时,形参列表必须先列出没有默认值的形参,再列出有默认值的形参。否则调用函数采用位置传参将出现错误。
  2. 错误演示示例如下:
def describe_pet(animal_type='dog',pet_name):
    """显示宠物的信息"""
    print("\nI have a " + animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet('hamster','harry') 
describe_pet('harry')           
    def describe_pet(animal_type='dog',pet_name):
                                       ^^^^^^^^
SyntaxError: non-default argument follows default argument
  1. 正确演示示例如下:
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('willie')
describe_pet('harry','hamster')
I have a dog.
My dog's name is Willie.

I have a hamster.
My hamster's name is Harry.

2.4 等效的函数调用

  1. 可混合使用位置实参、关键字实参、默认值 3种有效的函数调用方式
  2. 演示示例如下:
def describe_pet(pet_name,animal_type='dog'):
    
#一条名为Willie的小狗
def describe_pet('willie'):
def describe_pet(pet_name='willie'):

# 一条名为Harry的仓鼠
def describe_pet('harry','hamster'):
def describe_pet(pet_name='harry', animal_type='hamster'):
def describe_pet(animal_type='hamster',pet_name='harry'):

2.5 避免实参错误

  1. 当提供的实参多于或少于函数完成其工作所需的信息时,将出现实参不匹配错误
  2. 演示示例如下:
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()
Traceback (most recent call last):
  File "E:\GBB_01.技术\03、Python\002、Python编程从入门到实践\0001、Python操作\python_work\第8章.函数.py", 
  line 82, in <module>
    describe_pet()
TypeError: describe_pet() missing 2 required positional arguments: 'animal_type' and 'pet_name'

3. 返回值

  1. 函数并非总是直接显示输出
  2. 函数返回的值称为返回值
  3. 在函数中,可使用return语句将值返回到调用函数的代码行

3.1 返回简单值

  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)
Jimi Hendrix

3.2 让实参变成可选的

  1. 可选值让函数能够处理各种不同情形
  2. 下面这个示例既可以处理只含名和姓的人,也可以处理含名、中间名、姓的人
  3. 如果包含中间名,需要确保它是最后一个实参
  4. 演示示例如下:
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)

musician = get_formatted_name('john','hooker','lee')
print(musician)
Jimi Hendrix
John Lee Hooker

3.3 返回字典

  1. 函数可返回任何类型的数值,包括列表和字典等较复杂的数据结构
  2. 演示示例如下:
def build_person(first_name,last_name):
    """返回一个字典,其中包含有关一个人的信息"""
    person = {'first':first_name,'last':last_name}
    return person

musician = build_person('jimi','hendrix')
print(musician)
{'first': 'jimi', 'last': 'hendrix'}
  1. 函数接收的信息放在此类数据结构中,不仅可以打印这些信息,还可以对其进行扩展处理
  2. 演示示例如下:
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)
print(musician)
{'first': 'jimi', 'last': 'hendrix', 'age': 27}

3.4 结合使用函数和while循环

  1. 演示示例如下:
def get_formatted_name(first_name,last_name):
    """返回整洁的姓名"""
    full_name = first_name + ' ' + last_name
    return full_name.title()
    
while True:
    print("\nPlease tell me your name: ")
    print("(enter '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

    formatted_name = get_formatted_name(f_name,l_name)
    print("\nHello," + formatted_name + "!")
Please tell me your name: 
(enter 'q' at any time to quit)
First name: eric
Last name: matthes

Hello,Eric Matthes!

Please tell me your name: 
(enter 'q' at any time to quit)
First name: q

4. 传递列表

  1. 向函数传递列表很有用,列表包含的可能是名字、数字、或更复杂的对象(如字典)
  2. 列表传递给函数后,函数就能直接访问其内容
  3. 演示示例如下:
def greet_users(names):
    """向列表中的每位用户都发出简单的问候"""
    for name in names:
        msg = "Hello," + name.title() + "!"
        print(msg)

usernames = ['hannah','ty','margot']
greet_users(usernames)
Hello,Hannah!
Hello,Ty!
Hello,Margot!

4.1 在函数中修改列表

  1. 演示示例如下:(未使用函数版本)
unprinted_designs = ['iphone case','robot pendant','dodecahedron']
completed_models = []

while unprinted_designs:
    current__design = unprinted_designs.pop()
    print("Printing model: " + current__design)
    completed_models.append(current__design)

print("\nThe following models have been printed:")
for completed_model in completed_models:
    print(completed_model)
Printing model: dodecahedron
Printing model: robot pendant
Printing model: iphone case

The following models have been printed:
dodecahedron
robot pendant
iphone case
  1. 演示示例如下:(使用函数版本)
def print_models(unprinted_designs,completed_models):
    """
    模拟打印每个设计,直到没有未打印的设计为止
    打印每个设计后,都将其移列表completed_models中
     """
    while unprinted_designs:
        current_design = unprinted_designs.pop()
        #模拟根据设计制作3D打印模型的过程
        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)
Printing model: dodecahedron
Printing model: robot pendant
Printing model: iphone case

The following models have been printed:
dodecahedron
robot pendant
iphone case
  1. 使用函数的版本,程序更容易扩展和维护
  2. 采用描述性的函数名可以让别人阅读代码时可读性强

4.2 禁止函数修改列表

  1. 解决需要禁止函数修改列表,可向函数传递列表的副本而不是原件,这样函数只能修改副本,而不能对原件进行改动
  2. 向函数传递列表副本可保留原始列表的内容,但一般不建议这么做,除非确实有需要
  3. 让函数使用现成列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤为如此
  4. 前述示例创建列表副本演示如下:
print_models(unprinted_designs[:],completed_models)

5. 传递任意数量的实参

  1. Python允许函数从调用语句中收集任意数量的实参
  2. 下面的示例中 *toppings 的星号让Python创建一个名为toppings的空元祖,将收到的所有制都封装进去,即时函数只收到一个值也是如此
  3. 演示示例如下:
def make_pizza(*toppings):
    """打印顾客点的所有配料"""
    print(toppings)

make_pizza('pepperoni')
make_pizza('mushrooms','green peppers','extra cheese')
('pepperoni',)
('mushrooms', 'green peppers', 'extra cheese')
  1. 演示示例2如下:
def make_pizza(*toppings):
    """概述要制作的比萨"""
    print("\nMaking a pizza with the following toppings:")
    for topping in toppings:
        print("- " + topping)

make_pizza('pepperoni')
make_pizza('mushroons','green peppers','extra cheese')
Making a pizza with the following toppings:
- pepperoni

Making a pizza with the following toppings:
- mushroons
- green peppers
- extra cheese

5.1 结合使用位置实参和任意数量实参

  1. 当函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后
  2. Python先匹配位置实参和关键字实参,余下的实参都匹配到最后一个形参中
  3. 演示示例如下:
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,'mushroons','green peppers','extra cheese')
Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushroons
- green peppers
- extra cheese

5.2 使用任意数量的关键字实参

  1. 当需要接受任意数量的实参,且预先不知道传递给函数的会是什么样的信息,此时可以将函数编写成能够接受任意数量的键值对
  2. 下面示例中的 **user_info 的两个星号表示让Python创建一个名为 user_info 的空字典
  3. 演示示例如下:
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)
{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}

6. 将函数存储在模块中

  1. 模块是扩展名为.py 的文件
  2. 将函数存储在模块这种独立文件中,再通过 import 语句将模块导入到主程序中
  3. 通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上
  4. 可使不同的程序使用函数

6.1 导入整个模块

  1. 要调用被导入模块中的函数,可指定导入模块的名称和函数名,中间用句点分隔它们
  2. module_name.function_name()
  3. 演示示例如下:
    pizza.py
def make_pizza(size,*toppings):
    """概述要制作的比萨"""
    print("\nMaking a " + str(size) +
          "-inch pizza with the following toppings:")
    for topping in toppings:
        print("- " + topping)

making_pizzas

import pizza

pizza.make_pizza(16,'pepperoni')
pizza.make_pizza(12,'mushrooms','green peppers','extra cheese')
Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

6.2 导入特定的函数

  1. 导入模块中特定函数:from module_name import function_name
  2. 导入模块中任意数量函数:from module_name import function_0,function_1,function_2
  3. 使用这种方式,调用函数时只需要指定函数名即可,不需要在前面加上模块名.
  4. 演示示例如下:
from pizza import make_pizza

make_pizza(16,'pepperoni')
make_pizza(12,'mushrooms','green peppers','extra cheese')

6.3 使用as给函数指定别名

  1. 若导入的函数名称可能与程序中现有名称冲突,或者函数名称太长,可以给函数起别名
  2. from module_name import function_name as fn
  3. 演示示例如下:
from pizza import make_pizza as mp

mp(16,'pepperoni')
mp(12,'mushrooms','green peppers','extra cheese')

6.4 使用as给模块指定别名

  1. 给模块指定别名
  2. import module_name as mn
  3. 演示示例如下:
import pizza as p

p.make_pizza(16,'pepperoni')
p.make_pizza(12,'mushrooms','green peppers','extra cheese')

6.5 导入模块中的所有函数

  1. 导入模块中所有函数
  2. from module_name import *
  3. 不推荐采用,了解即可
  4. 演示示例如下:
from pizza import *

make_pizza(16,'pepperoni')
make_pizza(12,'mushrooms','green peppers','extra cheese')

7. 函数编写指南

  1. 给函数指定描述性名称时,且只在其中使用小写字母和下划线
  2. 给模块命名时,也应遵循上述约定
  3. 每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式
  4. 给形参指定默认值时,等号两边不要有空格
def function_name(parameter_0,parameter_1='default value'):
  1. 函数调用中的关键字实参,也应遵循这种约定
function_name(value_0,parameter_1='value')
  1. 如果形参很多导致函数定义长度超过79字符,可在函数定义中输入左括号后按回车键,并在下一行按两次tab键,
    从而将形参列表和只缩进一层的函数体区分开来
def function_name(
        parameter_0,parameter_1,parameter_2,
        parameter_3,parameter_4,parameter_5):
    function body...
  1. 如果程序或模块中包含多个函数,可使用两个空行将相邻的函数区分开
  2. 所有的 import 语句都应放在文件开头,唯一例外的情况是,在文件开头使用了注释来描述整个程序

8. 章节跳转

  1. Python编程 从入门到实践 第一章 起步
  2. Python编程 从入门到实践 第二章 变量和简单数据类型
  3. Python编程 从入门到实践 第三章 列表简介
  4. Python编程 从入门到实践 第四章 列表操作
  5. Python编程 从入门到实践 第五章 if语句
  6. Python编程 从入门到实践 第六章 字典
  7. Python编程 从入门到实践 第七章 用户输入和while循环
  8. Python编程 从入门到实践 第八章 函数
  9. Python编程 从入门到实践 第九章 类
  10. Python编程 从入门到实践 第十章 文件和异常
  11. Python编程 从入门到实践 第十一章 测试代码
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值