文章目录
前言
本文的主要内容是Python中函数介绍及其使用,具体包括定义函数、传递参数、函数返回值、传递列表与任意数量的实参以及将函数存储在模块中等部分,文中附有代码以及相应的运行结果辅助理解。
一、定义函数
函数是带有名字的代码块,其用于完成具体的工作,有时候需要在程序中多次执行同一项任务,如果每次都写相同的代码,程序就会显得又长又繁琐,可读性也不好,此时可以将这一项特定的任务写为函数体,在程序需要的时候调用执行该函数即可,这样一来,程序的编写、可读性、测试和修改都将变得更加容易。
下面是最简单的函数应用,即调用函数打印一句话。
def msg_print():
"""打印消息""" #这行是文档字符串的注释,用来解释函数的功能
print('Hello!') #后面的所有缩进行构成了函数体
msg_print() #调用函数
运行结果如下图所示。
在上面的例子中,函数名后面的括号内是空的,一般情况下,在调用函数时都会向函数传递参数信息。
在函数定义时传递的参数是形参,形参是函数完成其工作所需的一项信息;在函数调用时传递的参数是实参,实参是调用函数时传递给函数的信息。
下面是向函数传递参数的例子。
def msg_print(name): #这里的name是形参
"""打印消息"""
print('Hello, ' + name.title() + '!')
msg_print('emma') #这里的'emma'是实参
运行结果如下图所示。
二、传递实参
函数定义中可能包含多个形参,因此函数在调用时也就包含多个实参。向函数传递实参的方式很多,有位置实参、关键字实参,还可使用列表和字典。
1.位置实参
使用位置实参要求实参的顺序与形参的顺序相同,否则在调用函数的过程中会发生类型错误或者逻辑错误。
下面是位置实参应用的例子。
def user_info(name, fruit):
"""打印用户信息"""
print('My name is ' + name.title() + '.')
print('I like ' + fruit + ' best.')
user_info('emma','apple') #正确调用,实参与形参顺序一一对应
user_info('apple', 'emma') #错误调用
运行结果如下图所示。
由运行结果可以看到,位置实参一定要和形参顺序一致,这样才不会使错误发生。
2.关键字实参
关键字实参中每个实参都是由变量名和值组成的,它传递给函数的实参是名称值对,因为在实参中将名称和值已经关联起来了,所以无需再考虑函数调用中的实参顺序。
下面是关键字实参应用的例子。
def user_info(name, fruit):
"""打印用户信息"""
print('My name is ' + name.title() + '.')
print('I like ' + fruit + ' best.')
user_info(name = 'emma',fruit = 'apple')
user_info(fruit = 'apple', name = 'emma')
运行结果如下图所示。
由运行结果可知,使用关键字实参无需再担心实参与形参的顺序对应一致,只需要将名称和值对应上即可。
3.给形参指定默认值
编写函数时,可给每个形参指定默认值,若调用的函数提供了实参,Python将使用指定的实参值,如果没有提供实参,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参。
下面是给形参指定默认值的例子。
def user_info(name='emma', fruit='apple'): #给形参指定默认值
"""打印用户信息"""
print('My name is ' + name.title() + '.')
print('I like ' + fruit + ' best.')
user_info() #省略已有默认值的实参
user_info('alice') #只传一个实参,默认传给第一个位置
user_info(fruit='pear') #如果要传参给非第一位置,使用关键字实参的方法
user_info('lisa', 'banana') #提供实参则覆盖默认值
运行结果如下图所示。
三、函数返回值
函数并非总是直接显示输出,它也可以处理一些数据并返回一个或一组值,函数返回的值被称为返回值。在函数中,可使用return语句将值返回到调用函数的代码行,返回值能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。
1.返回简单值
下面是函数返回简单值的例子。
def name(first_name, last_name):
"""返回用户全名"""
full_name = first_name.title() + ' ' +last_name.title()
return full_name
print(name('lebron','james')) #调用函数并打印
运行结果如下图所示。
当然有的人有中间名,这就用到了上面学到的默认值,将中间名形参默认设置为空,这样在函数调用时就能够应对有中间名的情况了。
下面是该例子的扩展。
def name(first_name, last_name, middle_name=''):
"""返回用户全名"""
if middle_name: #中间名非空
full_name = first_name.title() + ' ' + middle_name.title() + ' ' + last_name.title()
else:
full_name = first_name.title() + ' ' +last_name.title()
return full_name
print(name('lebron', 'james')) #调用函数并打印
print(name('john', 'green', 'joe')) #调用函数并打印
运行结果如下图所示。
2.返回字典
函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。
下面是函数返回字典的例子。
def name(first_name, last_name):
"""返回一个字典"""
full_name = {'first_name': first_name, 'last_name': last_name}
return full_name
print(name('lebron', 'james')) #调用函数打印字典
运行结果如下图所示。
3.结合使用函数和while 循环
下面是一个结合使用函数和while循环的例子。
def name(first_name, last_name):
"""返回用户全名"""
full_name = first_name.title() + ' ' +last_name.title()
return full_name
while True:
first_name = input('Please input your first name: ')
last_name = input('Please input your last name: ') #用户输入
print('Your name is ' + name(first_name, last_name) + '.') #调用函数并打印
quit = input("Enter 'q' to end, and other keys to continue.") #根据用户输入决定是否退出while循环
if quit == 'q':
break
运行结果如下图所示。
四、传递列表
有时候,将列表传递给函数可以提高处理列表的效率。此外,在函数中对列表所做的任何修改都是永久性的。
1.在函数中调用列表
下面是一个在函数中调用列表的简单例子。
def fruit_msg(fruits):
"""访问列表中的每个元素"""
for fruit in fruits: #逐个访问列表元素
print('I like ' + fruit + '.')
fruits = ['grapes', 'apples', 'bananas', 'oranges', 'pears']
fruit_msg(fruits) #调用函数访问列表
运行结果如下图所示。
2.在函数中修改列表
在函数中不仅可以调用列表,还可以修改列表,不过这种修改是永久性的。
下面是一个在函数中修改列表的例子。
def print_msg(fruit_1, fruit_2):
"""修改列表,打印列表fruit_1中的每个元素并删除,将其添加到列表fruit_2中"""
while fruit_1: #列表fruit_1非空时执行while语句
fruit = fruit_1.pop() #逐个删除列表fruit_1中的元素
print('I like ' + fruit + '.')
fruit_2.append(fruit) #将删除的元素添加到列表fruit_2中
def print_element(fruits):
"""遍历列表元素"""
for fruit in fruits:
print('\t' + fruit)
fruit_1 = ['grapes', 'apples', 'bananas', 'oranges', 'pears']
fruit_2 = []
print_msg(fruit_1, fruit_2) #调用函数修改列表,这里传递的是原列表
print('列表fruit_1的元素: ')
print_element(fruit_1) #遍历列表fruit_1
print('列表fruit_2的元素: ')
print_element(fruit_2) #遍历列表fruit_2
运行结果如下图所示。
3.禁止在函数中修改列表
上面已经提到过了,在函数中对列表所做的任何修改都是永久性的,有时候可能需要保留原列表,这时就可以向函数传递列表的副本。
下面是禁止在函数中修改列表的例子。
def print_msg(fruit_1, fruit_2):
"""修改列表,打印列表fruit_1中的每个元素并删除,将其添加到列表fruit_2中"""
while fruit_1: #列表fruit_1非空时执行while语句
fruit = fruit_1.pop() #逐个删除列表fruit_1中的元素
print('I like ' + fruit + '.')
fruit_2.append(fruit) #将删除的元素添加到列表fruit_2中
def print_element(fruits):
"""遍历列表元素"""
for fruit in fruits:
print('\t' + fruit)
fruit_1 = ['grapes', 'apples', 'bananas', 'oranges', 'pears']
fruit_2 = []
print_msg(fruit_1[:], fruit_2) #调用函数修改列表,这里传递的是原列表的副本
print('列表fruit_1的元素: ')
print_element(fruit_1) #遍历列表fruit_1
print('列表fruit_2的元素: ')
print_element(fruit_2) #遍历列表fruit_2
运行结果如下图所示。
对比上面两段代码,只有一行发生了简单的变化,就是在给函数传递原列表时,传递给其列表的副本即可,这样在执行完程序时原列表就不会发生变化。
五、传递任意数量的实参
有时候,我们预先不知道函数需要接受多少个实参,不过Python允许函数从调用语句中收集任意数量的实参。
1.传递任意数量实参的简单例子
下面是一个传递任意数量实参的简单例子。
def print_msg(*fruits):
"""打印所有信息"""
print(fruits)
print_msg('apples')
print_msg('bananas', 'pears', 'mangoes')
运行结果如下图所示。
由上面的运行结果可以看出,传递的任意数量实参存储在元组中,我们也可以改写代码遍历元组。
改写后的代码如下。
def print_msg(*fruits):
"""打印所有信息"""
for fruit in fruits: #遍历元组
print('I like ' + fruit + '.')
print_msg('apples')
print_msg('bananas', 'pears', 'mangoes')
运行结果如下图所示。
2.结合使用位置实参和任意数量实参
如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后,Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。
下面是结合使用位置实参和任意数量实参的例子。
def print_msg(name, age, *fruits): #传递不同类型的参数
"""结合使用位置实参和任意数量实参"""
print('My name is ' + name.title() + ', I am ' + str(age) +' years old, and I like :')
for fruit in fruits: #遍历元组
print('\t' + fruit)
print_msg('emma', 12, 'apples')
print_msg('lisa', 20, 'bananas', 'pears', 'mangoes')
运行结果如下图所示。
3.使用任意数量的关键字实参
有时候需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息,在这种情况下可将函数编写成能够接受任意数量的键值对,将其写入到字典中。
下面是使用任意数量的关键字实参的例子。
def user_info(name, age, **other_info): #注意这里一定是双星号
"""使用任意数量的关键字实参"""
users = {} #创建空字典
users['name'] = name #在字典中加入已知的键值对
users['age'] = age
for key, value in other_info.items(): #遍历其他参数信息添加到字典中
users[key] = value
return users
print(user_info('Emma', 12, favorite_color='red', favorite_fruit='apple')) #调用函数并打印
print(user_info('Lisa', 20, favorite_color='green', favorite_fruit='watermelon', favorite_sport='basketball'))
运行结果如下图所示。
六、将函数存储在模块中
函数的优点之一是可将代码块与主程序分离,将函数存储在被称为模块的独立文件中,再将模块导入到主程序中,import语句允许在当前运行的程序文件中使用模块中的代码。
通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上,此外,这样做还能让你在不同的程序中重用函数。将函数存储在独立文件中后,这些文件就可以共享。
1.导入整个模块
要让函数是可导入的,得先创建模块,模块是扩展名为.py的文件,其中包含要导入到主程序中的代码。
在上面的例子中进行修改,先新建一个名为function.py的模块文件,在其中写入如下代码。
def print_msg(fruit_1, fruit_2):
"""修改列表,打印列表fruit_1中的每个元素并删除,将其添加到列表fruit_2中"""
while fruit_1: #列表fruit_1非空时执行while语句
fruit = fruit_1.pop() #逐个删除列表fruit_1中的元素
print('I like ' + fruit + '.')
fruit_2.append(fruit) #将删除的元素添加到列表fruit_2中
def print_element(fruits):
"""遍历列表元素"""
for fruit in fruits:
print('\t' + fruit)
然后在主程序文件中调用该模块中的函数,代码如下。
import function #导入文件function.py,即将其中的所有函数都复制到这个程序中
fruit_1 = ['grapes', 'apples', 'bananas', 'oranges', 'pears']
fruit_2 = []
function.print_msg(fruit_1[:], fruit_2)
#调用被导入模块中的函数时,可指定导入的模块的名称和函数名,并用句点分隔它们
print('列表fruit_1的元素: ')
function.print_element(fruit_1) #遍历列表fruit_1
print('列表fruit_2的元素: ')
function.print_element(fruit_2) #遍历列表fruit_2
上面的例子在调用函数时需要使用模块名、句点以及函数名才能完成函数的调用。
运行结果如下图所示。
可以看到,上面代码的运行结果与函数和程序在一个文件中的运行结果一致。
2.使用as给模块指定别名
要给模块指定别名,可以在导入模块时使用as给模块指定别名,代码示例如下。
import function as f
#导入文件function.py到主程序中并给其指定别名为f
下面的这段主程序代码的功能和上面的主程序代码功能一致。
import function as f #导入模块function并给其指定别名为f
fruit_1 = ['grapes', 'apples', 'bananas', 'oranges', 'pears']
fruit_2 = []
f.print_msg(fruit_1[:], fruit_2) #调用函数使用模块名时用别名
print('列表fruit_1的元素: ')
f.print_element(fruit_1)
print('列表fruit_2的元素: ')
f.print_element(fruit_2)
3.导入特定的函数
模块中存储的函数一般有很多,有时候我们只需要导入特定的函数。
比如要导入上面function.py模块中的print_msg()函数,可以用如下代码。
from function import print_msg
#从模块名为function.py的文件中导入函数print_msg,注意这里的函数不带括号
如果要从模块中导入多个函数,可以用逗号隔开,代码示例如下。
from function import print_msg, print_element
#从模块名为function.py的文件中导入函数print_msg和print_element,注意这里的函数不带括号
下面这段主程序代码与上面的主程序代码功能是一致的,在调用函数时直接指定函数名称即可。
from function import print_msg, print_element #从模块中导入特定的函数
fruit_1 = ['grapes', 'apples', 'bananas', 'oranges', 'pears']
fruit_2 = []
print_msg(fruit_1[:], fruit_2) #调用函数时直接指定函数名称,无需使用句点
print('列表fruit_1的元素: ')
print_element(fruit_1) #遍历列表fruit_1
print('列表fruit_2的元素: ')
print_element(fruit_2) #遍历列表fruit_2
4.使用as给函数指定别名
如果要导入的函数名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名,即函数的另一个名称,类似于外号,要给函数指定别名,需要在导入它时使用as指定别名。
代码示例如下。
from function import print_msg as pm
#从模块名为function.py的文件中导入函数print_msg,并指定其别名为pm,这样在使用时用pm即可
需要注意的是,给函数指定别名后,在主程序中调用该函数只能用其别名,原来的函数名将不能使用。
下面的这段主程序代码的功能也和上面的主程序代码功能一致,在调用函数时使用其别名调用。
from function import print_msg as pm, print_element as pe #从模块中导入特定的函数并起别名
fruit_1 = ['grapes', 'apples', 'bananas', 'oranges', 'pears']
fruit_2 = []
pm(fruit_1[:], fruit_2) #调用函数时只能使用别名
print('列表fruit_1的元素: ')
pe(fruit_1) #遍历列表fruit_1
print('列表fruit_2的元素: ')
pe(fruit_2) #遍历列表fruit_2
5.导入模块中的所有函数
导入模块中的所有函数使用如下代码。
from function import *
#从模块名为function.py的文件中导入所有函数
导入模块中的所有函数后,调用函数时不需要用句点,直接使用函数名调用即可。
下面这段主程序代码与上面的主程序代码功能也是一致的。
from function import * #从模块中导入所有的函数
fruit_1 = ['grapes', 'apples', 'bananas', 'oranges', 'pears']
fruit_2 = []
print_msg(fruit_1[:], fruit_2) #调用函数时直接指定函数名称
print('列表fruit_1的元素: ')
print_element(fruit_1) #遍历列表fruit_1
print('列表fruit_2的元素: ')
print_element(fruit_2) #遍历列表fruit_2
七、猜数字游戏
还记得本书前言中的这个猜数字游戏吗?上一篇文章Python中用户输入与while循环中已经编写过了。
下面是使用函数实现该游戏的代码。
import random
def func(input_num, thinking_num):
"""定义函数用于比较输入数与预想数的大小,两者相等时退出函数"""
while input_num != thinking_num:
if input_num < thinking_num:
input_num = input("Too low! Guess again: ")
input_num = int(input_num)
elif input_num > thinking_num:
input_num = input("Too high! Guess again: ")
input_num = int(input_num)
sign = True #标志位置为 True
while sign:
number = random.randint(1, 100) # 随机生成一个1-100内的随机数作为预想数
num = input("I'm thinking of a number! Try to guess the number I'm thinking of: ")
func(int(num), number) #调用函数比较用户输入数值与预想数值的大小关系
y_or_n = input("That's it! Would you like to play again? (yes/no): ")
if y_or_n == 'no': #用户输入no时退出游戏
sign = False #标志位置为 False
print("Thanks for playing!")
运行结果如下图所示。
由上面的运行结果可以看到,代码能够按照要求运行并给予用户反馈,这就是一个简单的人机交互小游戏。
总结
以上就是Python中函数介绍及其使用的所有内容了,在编写函数时,应给函数指定描述性名称,且只在其中使用小写字母和下划线,给模块命名时也应如此,每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面。总之,在编写函数的过程中应尽可能的规范编写代码,这样在调用函数时,不管是自己还是别人都能够很好的理解。
本文参考书目:Python 编程 :从入门到实践 / (美) 埃里克•马瑟斯(Eric Matthes)著;袁国忠译