【Python开发】6. 函数和模块

本文专栏:Python开发笔记  点击查看系列文章

1. 函数的定义

函数 是带名字的代码块,用于完成具体的工作。

要执行函数定义的特定任务,可调用该函数。需要在程序中多次执行同一项任务时,你无需反复编写完成该任务的代码,而只需调用执行该任务的函数,让Python运行其中的代码。你将发现,通过使用函数,程序的编写、阅读、测试和修复都将更容易。

在Python中,函数使用关键字 def 来定义,并需要指明 函数名 ,以及函数需要什么样的 信息 ,最后,定义以 冒号结尾

示例:

# 定义一个名为greet_user的函数,函数需要的信息为空
def greet_user():
    """这里是函数体内的代码,实现某一具体功能"""
    print('Hello!')


# 调用函数
greet_user()

当然,可以给函数传递参数。

示例:

# 定义一个名为greet_user的函数,函数需要的信息为username
def greet_user(username):
    """这里是函数体内的代码,实现某一具体功能"""
    print('Hello,' + username)


# 调用函数
greet_user('Zhang San')

关于 形参实参

  • 形参:是指函数完成其工作所需要的一项信息。如上面示例中,函数定义的 username 就是形参。
  • 实参:调用函数时传递给函数的信息。如上面示例中,调用函数时的 'Zhang San' 就是实参。

2. 传递实参

2.1 基本传参

鉴于函数定义时,可能包含多个形参,所以函数调用中也可能包含多个实参。

向函数传递实参的方式很多,可使用 位置实参 ,这要求实参的顺序与形参的顺序相同;也可使用 关键字实参 ,其中每个实参都由变量名和值组成;还可使用 默认值列表字典

2.1.1 位置实参

在调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参

所以 位置实参是基于实参的顺序,使得实参和形参的位置一一对应

示例:

def get_days(year, month):
    if month in [1, 3, 5, 7, 8, 10, 12]:
        print(str(year) + '年' + str(month) + '月有31天')
    elif month in [4, 6, 9, 11]:
        print(str(year) + '年' + str(month) + '月有30天')
    elif month == 2:
        if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
            print(str(year) + '年' + str(month) + '月有29天')
        else:
            print(str(year) + '年' + str(month) + '月有28天')
    else:
        print('输入错误')


# 调用函数
get_days(2020, 9)
get_days(2020, 2)
get_days(2021, 2)

在这个示例的调用函数时,直接填写实参,这里要保证实参的顺序和定义函数时的形参顺序一致

如果把 20209 的顺序颠倒,即写成:get_days(2, 2021) 会出现输入上的 实参错误

2.1.2 关键字实参

关键字实参 是传递给函数的 名称—值 对。这样直接在调用函数时,将名称和值关联起来了,因此向函数传递实参时不会混淆。

关键字实参让你无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。

示例:

def get_days(year, month):
    if month in [1, 3, 5, 7, 8, 10, 12]:
        print(str(year) + '年' + str(month) + '月有31天')
    elif month in [4, 6, 9, 11]:
        print(str(year) + '年' + str(month) + '月有30天')
    elif month == 2:
        if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
            print(str(year) + '年' + str(month) + '月有29天')
        else:
            print(str(year) + '年' + str(month) + '月有28天')
    else:
        print('输入错误')


# 调用函数
get_days(year=2020, month=9)
get_days(month=2, year=2020)

如上面示例,两种函数的调用方法是等效的。

2.1.3 默认值

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

如果在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值。

使用默认值可简化函数调用,还可清楚地指出函数的典型用法。

示例:

def get_days(month, year=2020):
    if month in [1, 3, 5, 7, 8, 10, 12]:
        print(str(year) + '年' + str(month) + '月有31天')
    elif month in [4, 6, 9, 11]:
        print(str(year) + '年' + str(month) + '月有30天')
    elif month == 2:
        if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
            print(str(year) + '年' + str(month) + '月有29天')
        else:
            print(str(year) + '年' + str(month) + '月有28天')
    else:
        print('输入错误')


# 调用函数
get_days(month=2)
get_days(month=2, year=2022)

在上面这个示例中,给 year 的默认值是 2020 。如果调用函数时,未指定年份,则默认使用2020年。如 get_days(month=2) ,如果指定了年份,则使用指定的年份,如 get_days(month=2, year=2022)

注意:在函数定义时,含默认值的形参位置应该在不含默认值的形参之后。

def get_days(month, year=2020): 写法是正确的,def get_days(year=2020, month): 写法是错误的。

2.1.4 可选实参

可选实参和默认值类似,即定义函数时,将某个形参定义为空,并在函数体内对该参数是否输入进行判断。

2.2 传递列表

将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量的数据。

举个小例子,在已知列表末尾追加一个元素,如果直接将列表交给函数处理,那么函数把这个列表处理完成后,即使没有返回,原来的列表中数据也变了。

示例:

def test1(list):
    list.append(7)


list = [1, 2, 3, 4, 5, 6]
print(list)  # 这一行打印原列表
test1(list)
print(list)  # 这一行将执行函数后的列表打印

示例输出:

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]

但有时候,需要禁止函数修改列表。

这时,可以采用将列表的副本传递给函数的方法,阻止其修改原来列表。

示例:

def test1(list):
    list.append(7)


list = [1, 2, 3, 4, 5, 6]
print(list)  # 这一行打印原列表
test1(list[:]) # 这里传递的是列表的副本
print(list)  # 这一行将执行函数后的列表打印

示例输出:

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]

虽然向函数传递列表的副本可保留原始列表的内容,但除非有充分的理由需要传递副本,否则还是应该将原始列表传递给函数,因为让函数使用现成列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。

2.3 不定个数传参

有时候,你预先不知道函数需要接受多少个实参,好在Python允许函数从调用语句中收集任意数量的实参。

例如,有一个发送邀请函的函数,通知每个人参会时间,但无法确定本次会议有哪些人参会,所以可以将参会人姓名 name 形参改为 *names ,以实现不管调用语句提供多少实参,这个形参均将其收入。

示例:

def send_invitation(time, *names):
    for name in names:
        print('已通知 ' + name + ' 于 ' + time + ' 参会')


# 调用函数
send_invitation('2020-07-01 08:30', '张三', '李四', '王五', '赵六', '孙八')

示例输出:

已通知 张三 于 2020-07-01 08:30 参会
已通知 李四 于 2020-07-01 08:30 参会
已通知 王五 于 2020-07-01 08:30 参会
已通知 赵六 于 2020-07-01 08:30 参会
已通知 孙八 于 2020-07-01 08:30 参会

上面这个示例中,是实参的格式不确定。

还有一种情况,是形参的数量不确定。

比如一个人的个人简介,首先姓名是必须存在的,而其他的个人信息,比如居住地、学历、公司等信息,均不确定,所以可以采用下面这种形式来接收。

示例:构建个人信息字典

def build_profile(name, **infos):
    profile = {}
    profile['name'] = name
    for key, value in infos.items():
        profile[key] = value
    return profile


# 调用函数
user_profile = build_profile('张三', location='湖北武汉', school='武汉理工', college='计算机学院')
print(user_profile)

示例输出:

{'name': '张三', 'location': '湖北武汉', 'school': '武汉理工', 'college': '计算机学院'}

3. 返回值

函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值。

函数返回的值被称为**返回值。在函数中,可使用return** 语句将值返回到调用函数的代码行。

返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。

3.1 简单的返回值

最简单的返回类型是给函数输入输入,函数处理完毕,返回一个值。

示例:输入姓和名,返回整洁的姓名

def get_formatted_name(first_name, last_name):
    full_name = first_name + ' ' + last_name;
    return full_name.title()


# 调用函数
name = get_formatted_name('jim', 'hendrix')
print(name)

示例输出:

Jim Hendrix
3.2 返回字典等

函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。

示例:

def build_student(no, name, college, age):
    student = {
        'no': no,
        'name': name,
        'college': college,
        'age': age
    }
    return student


# 调用函数
student = build_student(20200101, '张三', '计算机学院', 20)
print(student)

示例输出:

{'no': 20200101, 'name': '张三', 'college': '计算机学院', 'age': 20}

4. 函数与模块

函数的优点之一是,使用它们可将代码块与主程序分离。通过给函数指定描述性名称,可让主程序容易理解得多。

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

主要的使用方法如下。

4.1 导入整个模块

示例:

day.py

def get_days(year, month):
    if month in [1, 3, 5, 7, 8, 10, 12]:
        return 31
    elif month in [4, 6, 9, 11]:
        return 30
    elif month == 2:
        if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
            return 29
        else:
            return 28
    else:
        return 0

temp.py

import day

print(day.get_days(2020, 2))

示例输出:

29

在这个示例中,通过 import 关键字将 day.py 这个模块引入,然后在 temp.py 中通过点运算符将该函数引用。

4.2 导入所有&特定函数

当然也可以引入特定的函数,或者引入全部的函数,这样的话,就不用采用 模块名.函数名 的形式访问了,而是直接使用函数名访问

示例:引入全部函数

day.py同上

temp.py

from day import *

print(get_days(2020, 2))

输出结果同上。

示例:引入特定函数

day.py同上

temp.py

from day import get_days

print(get_days(2020, 2))

输出结果同上。

4.3 别名

可以给模块命名别名,也可以给模块的指定函数命名别名。示例如下。

示例:给模块命名别名(day.py同上)

import day as d

print(d.get_days(2020, 2))

示例:给函数命名别名(day.py同上)

from day import get_days as gd

print(gd(2020, 2))

5. 函数编写指南

  • 应给函数指定描述性名称,且只在其中使用小写字母和下划线。
  • 每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式。
  • 给形参指定默认值时,等号两边不要有空格。
  • 对于函数调用中的关键字实参,也应遵循等号两边不要有空格。
  • 如果形参很多,导致函数定义的长度超过了79字符,可在函数定义中输入左括号后按回车键,并在下一行按两次Tab键,从而将形参列表和只缩进一层的函数体区分开来。
  • 如果程序或模块包含多个函数,可使用两个空行将相邻的函数分开,这样将更容易知道前一个函数在什么地方结束,下一个函数从什么地方开始。
  • 所有的import 语句都应放在文件开头,唯一例外的情形是,在文件开头使用了注释来描述整个程序。

参考文献:

[1] Python编程:从入门到实践

如果有帮助,感谢动动小手点个赞 (๑•̀ㅂ•́)و✧❤

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾年之璐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值