本文专栏: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)
在这个示例的调用函数时,直接填写实参,这里要保证实参的顺序和定义函数时的形参顺序一致。
如果把 2020
和 9
的顺序颠倒,即写成: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编程:从入门到实践
如果有帮助,感谢动动小手点个赞 (๑•̀ㅂ•́)و✧❤