目录
函数
快速体验
- 所谓函数,就是把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用
- 函数的使用包含两个步骤:
- 定义函数 —— 封装 独立的功能
- 调用函数 —— 享受 封装 的成果
案例:洗衣服
# 早上洗衣服
print("打水")
print("洗衣服")
print("甩干")
# 中午洗衣服
print("打水")
print("洗衣服")
print("甩干")
# 晚上洗衣服
print("打水")
print("洗衣服")
print("甩干")
发现了问题:我们将有独立功能的代码封装成一个函数
def washing_machine(): # 洗衣机可以帮我们完成
print("打水")
print("洗衣服")
print("甩干")
# 优化后代码
# 早上洗衣服
washing_machine() # 打开洗衣机开关
# 中午洗衣服
washing_machine() # 打开洗衣机开关
# 晚上洗衣服
washing_machine() # 打开洗衣机开关
函数的创建与调用
创建函数
函数用 def
语句创建,语法如下:
def 函数名(参数列表): # 具体情况具体对待,参数可有可无
"""函数说明文档字符串"""
函数封装的代码
……
标题行由 def
关键字,函数的名字,以及参数的集合(如果有的话)组成
def
子句的剩余部分包括了一个可选的文档字串,和必需的函数体
函数名称 的命名应该 符合 标识符的命名规则
- 可以由 字母、下划线 和 数字 组成
- 不能以数字开头
- 不能与关键字重名
def washing_machine(): # 洗衣机可以帮我们完成
print("打水")
print("洗衣服")
print("甩干")
调用函数
使用一对圆括号 () 调用函数,如果没有圆括号,只是对函数的引用
任何输入的参数都必须放置在括号中
图例:
案例:加洗衣粉
def washing_machine(): # 洗衣机可以帮我们完成
print("打水")
print("加洗衣粉!!!")
print("洗衣服")
print("甩干")
# 早上洗衣服
washing_machine()
# 中午洗衣服
washing_machine()
# 晚上洗衣服
washing_machine()
总结
- 定义好函数之后,只表示这个函数封装了一段代码而已
- 如果不主动调用函数,函数是不会主动执行的
思考
-
能否将 函数调用 放在 函数定义 的上方?
- 不能!
- 因为在 使用函数名 调用函数之前,必须要保证
Python
已经知道函数的存在 - 否则控制台会提示
NameError: name '函数名' is not defined
(名称错误:这个名字没有被定义)
函数的参数
形参和实参
- 形参:定义 函数时,小括号中的参数,是用来接收参数用的,在函数内部 作为变量使用
- 实参:调用 函数时,小括号中的参数,是用来把数据传递到 函数内部 用的
问题
当我们想洗其他的东西,要手动改方法内部的代码:
def washing_machine(): # 洗衣机可以帮我们完成
print("打水")
print("加洗衣粉!!!")
print("洗床单") # 洗被套
print("甩干")
在函数内部有一定的变化的值:
def washing_machine(): # 洗衣机可以帮我们完成
print("打水")
print("加洗衣粉!!!")
print("洗衣服")
print("甩干")
washing_machine()
def washing_machine(): # 洗衣机可以帮我们完成
print("打水")
print("加洗衣粉!!!")
print("洗床单")
print("甩干")
washing_machine()
......
思考一下存在什么问题
函数只能处理 固定 的数据
如何解决?
- 如果能够把需要处理的数据,在调用函数时,传递到函数内部就好了!
传递参数
- 在函数名的后面的小括号内部填写 参数
- 多个参数之间使用
,
分隔 - 调用函数时,实参的个数需要与形参个数一致,实参将依次传递给形参
def washing_machine(something): # 洗衣机可以帮我们完成
print("打水")
print("加洗衣粉!!!")
print("洗" + something)
print("甩干")
# 洗衣服
washing_machine("衣服")
# 洗床单
washing_machine("床单")
图例
作用
- 函数,把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用
- 函数的参数,增加函数的 通用性,针对 相同的数据处理逻辑,能够 适应更多的数据
- 在函数 内部,把参数当做 变量 使用,进行需要的数据处理
- 函数调用时,按照函数定义的参数顺序,把 希望在函数内部处理的数据,通过参数 传递
位置参数
与 shell
脚本类似,程序名以及参数都以位置参数的方式传递给 python 程序,使用 sys
模块的 argv
列表接收
图例
默认参数
默认参数就是声明了 默认值 的参数,因为给参数赋予了默认值,所以在函数调用时,不向该参数传入值也是允许的
# 默认参数
# 1.如果没有手动给形参赋值,那么就用默认值
# 2.传递的实际参数优先级比默认参数要高
# 3.定义函数时,有默认值的参数一定放在没有默认值参数的后面
# 定义一个函数,计算两个数的和 num01 num02
def get_sum(num01, num02=100):
print(num01+num02)
get_sum(50) # num01 = 50 num02 = 100
get_sum(10, 20) # num01 = 10 num02 = 20
get_sum(1, 2) # num01 = 1 num02 = 2
def get_sum2(num01=30, num02=40):
print(num01+num02)
get_sum2() # num01=30 num02=40
# def get_sum1(num01=100, num02): 报错
# print(num01+num02)
函数的返回值
- 在程序开发中,有时候,会希望 一个函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理
- 返回值 是函数 完成工作后,最后 给调用者的 一个结果
- 在函数中使用
return
关键字可以返回结果 - 调用函数一方,可以 使用变量 来 接收 函数的返回结果
注意:
return
表示返回,表示方法执行结束,后续的代码都不会被执行
案例:取钱和查余额
# 查余额: 看,不带走,不能买东西
# 如果内部没有return语句,那么会默认返回None: return None
def chaxun():
print(100)
# return None
money1 = chaxun()
print("我取了:", money1) # 我取了: None
# 取钱: 将钱放自己兜里带走,能买东西
# return后跟的数据,叫函数的返回值
def quqian():
return 100 # 将100放自己兜里带走
money = quqian() # 调用quqian, 将100赋值给变量money
print("我取了:", money) # 我取了: 100
money -= 5
print("我买了1个冰淇凌,花了5元,还剩", money)
图例说明
没有 return
如果方法内部没有 return
语句,那么会默认返回 None,即 return None
练习 3:斐波那契数列函数
斐波那契数列函数
- 将斐波那契数列代码改为函数
- 数列长度由用户指定
- 要求把结果用 return 返回
版本一:方法内部直接打印
def gen_fib():
fib = [0, 1] # 定义列表,指定斐波那契数列的初始两个值
n = int(input('长度: ')) # 定义变量n, 此变量为用户要看到的列表fib中的元素个数
for i in range(n - 2):
fib.append(fib[-1] + fib[-2])
print(fib) # 打印列表fib
# 调用两次函数gen_fib()
gen_fib()
gen_fib()
版本二:带返回值
def gen_fib():
fib = [0, 1]
n = int(input('长度: '))
for i in range(n - 2):
fib.append(fib[-1] + fib[-2])
return fib # 返回最后生成的列表fib
# 调用函数gen_fib()
print(gen_fib())
版本三:带参数
def gen_fib(n):
fib = [0, 1]
for i in range(n - 2):
fib.append(fib[-1] + fib[-2])
return fib # 返回最后生成的列表fib
# 定义列表nlist, 将要产生的斐波那契数列的长度,作为列表nlist的元素
nlist = [10, 8, 6]
# 使用for循环,传递实参(nlist中的元素)给函数gen_fib(n),得到三组斐波那契数列
for i in nlist:
print(gen_fib(i))
练习4:复制文件函数
- 修改文件练习中的拷贝程序
- 将程序改为函数的形式
- 源文件和目标文件要求通过参数进行传递
- 实参要求来自于命令行
版本1:
# 定义函数copy(),实现指定单个文件拷贝的功能
def copy():
src_name = '/usr/bin/ls'
dst_name = '/tmp/list3'
# 以只读字节的方式打开源文件,fr
# 以写入字节的方式打开源文件,fw
fr = open(src_name, mode='rb')
fw = open(dst_name, mode='wb')
while True:
data = fr.read(4096)
if len(data) == 0:
break
fw.write(data)
fr.close()
fw.close()
copy() # 调用拷贝文件的函数copy()
版本2:
def copy(src_name, dst_name): # 定义函数copy(),实现任意文件的拷贝操作
# 以只读字节的方式打开源文件,赋值给变量fr
# 以写入字节的方式打开源文件,赋值给变量fw
fr = open(src_name, mode='rb')
fw = open(dst_name, mode='wb')
while True:
data = fr.read(4096)
if len(data) == 0:
break
fw.write(data)
fr.close()
fw.close()
copy(源文件路径, 目标文件路径)