前言:这个博客是为了记录我的学习过程也是为了能够有一种动力学习python,欢迎大家监督更新此博客。
(更新:2023年2月26日)
- 本博客所书写的文字类似于自述性的文字,官方话语较少,也有可能是自言自语的话,不过也比较真实记录学习过程
第八节:函数
一、函数的入门
1.定义函数
什么是函数呢,其实函数就是带名字的代码块,每一个代码块就是一个具体的功能,要执行函数的定义的特定任务时,就可以可调用该函数,我们就可以使用这个函数的功能。
# 一个最简单的函数代码
def hi()
"""显示最简单的问候语。"""
print("你好,年轻人!")
hi()
- 这就是最简单的一个函数,其中 def 的作用是告诉程序这是一个函数,所有的函数必须是def开头:
# 运行结果
你好,年轻人!
重点解释:
本例演示了最简单的函数结构。代码行使用关键字def 来告诉Python,你要定义一个函数。这是函数定义 ,向Python指出了函数名,还可能在圆括号内指出函数为完成任务需要什么样的信息。
在这里,函数名为hi() ,它不需要任何信息就能完成工作,因此括号是空的 (即便如此,括号也必不可少)。最后,定义以冒号结尾。
紧跟在def hi(): 后面的所有缩进行构成了 函数体。“”"处的文本是称为文档字符串 (docstring)的注释,描述了函数是做什么的。文档字符串用三引号括起,Python使用它们来生成有关程序中函数的文档。 代码行print("你好,年轻人!) 是函数体内的唯一一行代码,因此 hi() 只做一项工作:打印‘你好,年轻人!’
要使用这个函数,可调用它。函数调用让Python执行函数的代码。要调用函数, 可依次指定 函数名以及用圆括号括起的必要信息,所示。由于这个函数不需要任何信息,调用它时只需输入hi() 即可。和预期一样,它打印你好,年轻人!
2.向函数传递信息
在1中我们只是定义了一个函数,并没有向函数传递任何信息,只要稍作修改,就可以让hi()函数不止能显示 你好,年轻人!,还能将用户输入的名字作为抬头为此定义一个变量name:
def hi(name):
print(f"你好{name},年轻人!")
hi("小明")
- 代码hi(“小明”)调用函数hi(name) ,并向它提供执行函数调 用print() 所需的信息。这个函数接受你传递给它的名字,并向这个人发出问候:
# 运行结果
你好小明,年轻人!
3.函数的实参跟形参
这里引用官方解释:
在函数hi() 的定义中,变量nemr 是一个形参 (parameter),即函数完成工作所需的信息。在代码hi(‘小明’) 中,值’小明’是一个实参(argument),即调用函数时传递给函数的信息。
调用函数时,将要让函 数使用的信息放在圆括号内。在hi(“小明”)中,将实参’小明’ 传递给了函数hi() ,这个值被赋给了形参name 。
4.传递实参
1.位置实参
调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形 参。为此,最简单的关联方式是基于实参的顺序。这种关联方式称为位置实参 。
意思就是在调用这个函数时,实参所处函数的位置就是传递给相同位置形参的值:
def hi(name, age):
print(f"你好{name},年轻人现在才{age}!")
hi("小明", "18")
- 在位置关系看来,小明对应的就是name,18对应的就是age,这就是 位置实参
# 运行结果
你好小明,年轻人现在才18!
2.多次调用
一个函数可以根据程序的需要多次调用,并且每次调用都可以传递不同的信息来达到不同的效果:
def hi(name, age):
print(f"你好{name},年轻人现在才{age}!")
hi("小明", "18")
hi("小李", "23")
- 重复次数没有现在,传递实参没有限制
# 运行结果
你好小明,年轻人现在才18!
你好小李,年轻人现在才23!
2.关键字实参
除了调用的时候与函数的形参位置一致的实参输入方式,还有一种关键字实参,就是直接把实参要给哪个形参直接在调用的时候说清楚,这样不管位置放在哪里,这个实参的值都不会给错形参:
def hi(name, age):
print(f"你好{name},年轻人现在才{age}!")
hi(name="小明", age="18")
hi(age="小李", name="23"
- 这样不管实参的位置对于形参来说是一个什么样的关系,它只会按照关键字来传递值
# 运行结果
你好小明,年轻人现在才18!
你好23,年轻人现在才小李!
3.默认值
编写函数时,可给每个形参指定默认值 。在调用函数中给形参提供了实参时, Python将使用指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认 值后,可在函数调用中省略相应的实参。
默认值可为空
def hi(name, age='18'):
print(f"你好{name},年轻人现在才{age}!")
hi(name="小明")
hi(age="小李", name="23")
- 看上述代码中,对于小明是没有age函数的实参传递的,所以程序调用了默认参数age=18给下方程序运行,而小李是有23的实参传递,所以使用传递的实参。
# 运行结果
你好小明,年轻人现在才18!
你好23,年轻人现在才小李!
- 注意:使用默认值时,必须先在形参列表中列出没有默认值的形参,再列出有 默认值的实参。
5.返回值
函数并不是全部都是直接显示输出的,他还可以处理一些数据,并且可以返回一组或者一个值,函数的返回的值称为 返回值
1.返回简单值
下面来看一下简单的返回值
def run(a, b, c): # 创建函数进行运算
if a == "+":
d = b + c
elif a == "-":
d = b - c
elif a == "*":
d = b * c
elif a == "/":
d = b / c
elif a == "%":
d = b % c
return d
A = input("请问你要进行什么运算:")
B = input("请输入第一个数字:")
C = input("请输入第二个数字:")
yy = run(a=A, b=int(B), c=int(C)) # 将实参传递给形参,采用关键字实参,并将结果赋值给 yy
print(f"运算结果为:{yy}") # 接受返回值打印
- 注意程序是按照顺序来执行的,不能先调用再赋值,得先把ABC赋值,也可以把赋值过程写成函数,这种程度的就不用写注释了吧
# 运行结果
请问你要进行什么运算:+
请输入第一个数字:5
请输入第二个数字:6
运算结果为:11
2.返回字典
函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。例如,下面的函 数接受姓名的组成部分,并返回一个表示人的字典
def shen(xin_1, ming_1):
shen_1 = {'姓': xin_1, '名': ming_1}
return shen_1
name = shen('王', '磊')
print(name)
- 返回值存储在name中,为字典形式存在,其实返回值的类型取决与在函数中所返回的类型
# 运行结果
{'姓': '王', '名': '磊'}
6.传递列表
在使用中,可以向函数传递列表来达到同时处理众多数据的效果将列表传递给函数后,函数就能直接访问其内容。下面使用函数来 提高处理列表的效率。
def user(name):
for name_1 in name:
name_2 = f"你好,{name_1},欢迎你来到python的世界,加油学习!"
print(name_2)
username = ['小明', '夏利', '小白']
user(username)
- 运行结果会重复打印处理,这样在程序中,只要想打印同样的字符串,只需给出实参,并且调用函数即可
# 运行结果
你好,小明,欢迎你来到python的世界,加油学习!
你好,夏利,欢迎你来到python的世界,加油学习!
你好,小白,欢迎你来到python的世界,加油学习!
7.在函数中修改列表
如果我们需要重复处理相同的事情肯定是多次调用函数是最方便的也是运算速度最快的,如果将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量数据。
来看一家为用户提交的设计制作3D打印模型的公司。需要打印的设计存储在一个列表中,打印后将移到另一个列表中。下面是在使用函数的情况下模拟这个过程的代码:
# 创建一个函数print_list(list_0)
def print_list(list_0):
while list_0: # 循环这个列表
list_1 = list_0.pop() # 每次删除列表最后一位并且将值赋给list_1
print(f"执行复印操作,当前复印进度为:{list_1}") # 执行打印
accomplish_list.append(list_1) # 将当前的list_1的值往列accomplish_list的末尾添加
# 创建一个函数 show_list()
def show_list(accomplish_list_0):
for user in accomplish_list_0:
print(user) # 这里应该都看的懂了吧
accomplish_list = []
list_2 = ['phone case', 'robot pendant', 'dodecahedron']
print_list(list_2)
show_list(accomplish_list)
- 程序稍微繁琐了点,如果不是重复需求较多还是不是使用函数方便,大家可以尝试不使用函数来达到这个操作。
# 运行结果
执行复印操作,当前复印进度为:dodecahedron
执行复印操作,当前复印进度为:robot pendant
执行复印操作,当前复印进度为:phone case
dodecahedron
robot pendant
phone case
1.禁止函数修改列表
有时候,需要禁止函数修改列表。例如,假设像前一个示例那样,你有一个未打印 的设计列表,并编写了一个函数将这些设计移到打印好的模型列表中。你可能会做出这样的决定:即便打印好了所有设计,也要保留原来的未打印的设计列表,以供备案。
为解决这个问题,可向函数传递列表的副本而非原件。这 样,函数所做的任何修改都只影响副本,而原件丝毫不受影响。
要将列表的副本传递给函数,可以像下面这样做:
show_list(accomplish_list_0[:])
切片表示法[:] 创建列表的副本。在python中,如果不想清空未打印的设计列表,可像下面这样调用print_list() :
print_list(list_2[:])
这样函数print_list() 依然能够完成工作,因为它获得了所有未打印的设计的名称,但使用的是列表list_2的副本,而不是列表list_2本身。像以前一样,列表accomplish_list也将包含打印好的模型的名称,但函数所做的修改不会影响到列表。
8.传递任意数量的实参
有时候,预先不知道函数需要接受多少个实参,Python允许函数从调用语句中 收集任意数量的实参;想要传递任意数量的实参需要在创建函数是在形参前面加一个 星号(*):
def usert(*name):
print(name)
for names in name:
print(names)
usert('mushrooms', 'green peppers', 'extra cheese')
usert("你好")
- 在这个函数代码中,我们分别想函数usert传递了3个值和一个值,进行循环打印,*号的作用是让python创建一个名为name的空元组,并将收 到的所有值都封装到这个元组中。函数体内的函数调用print() 通过生成输出,证明Python能够处理使用一个值来调用函数的情形,也能处理使用三个值来调用函数的情形。它以类似的方式处理不同的调用。注意,Python将实参封装到一个元组中,即便函数只收到一个值:
('mushrooms', 'green peppers', 'extra cheese')
mushrooms
green peppers
extra cheese
('你好',)
你好
- 从结果来看我们两次分别向函数传递了三个实参跟一个实参,也没有进行关键词传递,只有位置实参,但是由于创建了元组,所以对于函数来说只传递了一个值过来。
# 运行结果
('mushrooms', 'green peppers', 'extra cheese')
mushrooms
green peppers
extra cheese
('你好',)
你好
9.使用任意数量的关键字实参
有时候,需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信 息。在这种情况下,可将函数编写成能够接受任意数量的键值对——调用语句提供 了多少就接受多少。
def bili_0(xin, ming, **user_int):
"""创建一个字典存储个人信息"""
user_int['xin_name'] = xin
user_int['ming_name'] = ming
return user_int
name = bili_0(xin="小", ming="明", gender='男', age='23')
print(name)
- 注意这里向函数bili()传递实参时,虽然xin和ming线传递,但是根据程序的运行顺序来看我们在调用函数的时候就已经把传递的gender和age传递进user_int的字典中了,然后程序才将xin、ming传递进字典,当然xin、ming的排列顺序也跟在程序的前后有关:
# 运行结果
{'gender': '男', 'age': '23', 'xin_name': '小', 'ming_name': '明'}
- 注意:你经常会看到形参名**kwargs ,它用于收集任意数量的关键字实参
二、将函数存储在模块中
1.导入整个模块
先来解释一下什么时模块,你在使用编辑器pycharm写程序的时候首先要先创建一个.py的文件,这个文件对于另一个.py的文件来说就是一个模块
要让函数是可导入的,得先创建模块。模块是扩展名为.py的文件,包含要导入到 程序中的代码。下面来创建一个包含函数calculate() 的模块。
- calculate.py
def run(a, b, c): # 创建函数进行运算
if a == "+":
d = b + c
elif a == "-":
d = b - c
elif a == "*":
d = b * c
elif a == "/":
d = b / c
elif a == "%":
d = b % c
return d
- run.py
import calculate
A = input("请问你要进行什么运算:")
B = input("请输入第一个数字:")
C = input("请输入第二个数字:")
yy = run(a=A, b=int(B), c=int(C)) # 将实参传递给形参,采用关键字实参,并将结果赋值给 yy
print(f"运算结果为:{yy}") # 接受返回值打印
- 注意!!文件夹命名避免中文命名,否则会报错,无法正确显示模块!!
- 要调用被导入模块中的函数,可指定被导入模块的名称calculate和函数名 run() ,并用句点分隔
# 运行结果 运行的是run.py文件
请问你要进行什么运算:+
请输入第一个数字:2
请输入第二个数字:5
运算结果为:7
2.导入特定的函数
还可以导入模块中的特定函数,这种导入方法的语法如下:
from calculate import run
# for 后面是模块名,import 后面是函数名
通过用逗号分隔函数名,可根据需要从模块中导入任意数量的函数
from calculate import run, run_1, run_2
# for 后面是模块名,import 后面是函数名
- 使用这种语法时,调用函数时无须使用句点。由于在import 语句中显式地导入了 函数run() ,调用时只需指定其名称即可。
3.使用as给函数指定别名
如果要导入函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的 别名 :函数的另一个名称,类似于外号。要给函数取这种特殊外号,需要在导入它时指定。
下面给函数run() 指定了别名mp() 。这是在import 语句中使用run as mp 实现的,关键字as 将函数重命名为指定的别名:
from calculate import run as mp
- 往后调用这个函数的时候就可以使用mp为调用函数名
4.使用as给模块指定别名
还可以给模块指定别名。通过给模块指定简短的别名(如给模块calculate 指定别名p ),让你能够更轻松地调用模块中的函数。相比于calculate.run()== p.run() 更为简洁:
import calculate as p
- 要调用calculate这个函数的run的时候,直接p.run即可
5.导入模块中的所有函数
使用星号(* )运算符可让Python导入模块中的所有函数:
from culcalate import *
- import 语句中的星号让Python将模块calculate 中的每个函数都复制到这个程序文件中。由于导入了每个函数,可通过名称来调用每个函数,而无须使用句点表示法。
这节到这里顺利结束辣,随着对代码的深入,发现代码的神奇之处非常多,再学完剩下的两张,我就准备写一个个人网站