第七章 函数
7.1 函数的定义
- 概念:功能(包裹一部分代码,实现某一功能,达成某一个目的)
- 特点:可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
7.1.1 函数基本格式
# 定义函数
def 函数名():
code
#调用函数
函数名()
7.1.2 函数的命名
- 命名规范:
- 字母、数字、下划线,且字母不能为数字
- 严格区分大小写,且不能使用关键字
- 函数命名有意义,且不能使用中文
- 驼峰命名法:
- 大驼峰命名法:每个单词的首字母要大写:
- mycar => Mycar
- 小驼峰命名法:除了第一个单词首字符小写外,剩下的单词首字母大写
- mycar => myCar
- 命名法:可以将不同单词用_拼接在一起
- mycar => my_car
- symmetric_difference
def ctf_99(): for i in range(1, 10): for j in range(1, i + 1): print("{:d}*{:d}={:2d}".format(i, j, i * j), end="") print() for i in range(5): ctf_99()
- 大驼峰命名法:每个单词的首字母要大写:
7.1.3 函数的参数
- 参数:函数运算时需要的值
- 形参:形式参数,在函数的定义处
- 普通形参(位置形参)
- 默认形参
- 普通收集形参
- 命名关键字形参
- 关键字收集形参
- 实参:实际参数,在函数的调用处
- 普通实参
- 关键字实参
- 形参:形式参数,在函数的定义处
- 原则:形参和实参要一 一对应
7.1.3.1 普通形参(位置形参)
# 定义函数
# a,b普通形参,在函数定义处
def func(a,b):
print(a)
print(b)
# 调用函数
# 1,2普通实参,在函数的调用处
func(1,2) # 1,2
7.1.3.2 默认形参
a,b默认形参,在函数定义处
如果给予实参,那么使用实参
如果没有给予实参,那么使用参数身上的默认值
"""
def func(a=1,b=2):
print(a)
print(b)
func() # 1,2
func(10,20) # 10,20
func(10) # 10,2
7.1.3.3 普通形参 + 默认形参
# 普通形参必须放到默认形参的前面不能调换位置
# 正确:
def func(a,b=2):
print(a)
print(b)
func(10)
# 错误:
def func(b=2,a):
print(a)
print(b)
func(10,20)
7.1.3.4 关键字实参
"""
1.如果都是关键字实参,可以任意调整实参的顺序
2.普通实参必须写在关键字实参的前面
"""
def func(a,b,c,d=1)
print(a,b)
print(c,d)
# 具体定制参数的值叫做关键字实参,在函数的调用处
func(a=1,b=2,c=7,d=6)
func(a=1,b=2,5,d=6) # error报错
7.1.3.5 收集形参
7.1.3.5.1 普通收集形参
-
专门用来收集那些多余的没人要的普通实参
-
收集之后,会把多余实参打包成一个元组
# arg => arguments
def func(a,b,c,*args):
print(a,b,c) # 1 2 3
print(args) # (4,5,6)
func(1,2,3,4,5,6)
# 任意个数值的累加和
def sum(*args):
total = 0
for i in args:
total += i
print(i)
sum(1,10)
7.1.3.5.2 关键字收集形参
- 专门用来收集那些多余的没人要的关键字实参
- 收集之后,会把多余关键字实参打包成一个字典
# kwargs => keyword arguments
def func(a,b**kwargs):
print(a,b) # 1 2
print(kwargs) # {'c': 3, 'd': 4}
func(a=1,b=2,c=3,d=4)
# 拼接任意个数值变成字符串
"""
班长: 赵万里
班花: 马春赔
吃瓜群: 美羊羊,沸羊羊,灰太狼
"""
def func (**kwargs):
strvar1 = ""
strvar2 = ""
# 定位职位信息
dic = {"monitor":"班长","classflower":"班花"}
print(kwargs)
for k,v in kwargs.items():
if k in dic:
# 将2次循环的结果通过+=拼接在一起
strvar1 += dic[k] + ":" + v +"\n"
print(strvar1)
else:
# 将3次循环的结果通过+=拼接在一起
strvar2 += v +","
print(strvar1.strip())
print("划水群众:",strvar2.strip(","))
func(monitor="赵万里",classflower="马春赔",water1="美羊羊",water2="沸羊羊",water3="灰太狼")
7.1.3.6 命名关键字参数
"""
# 命名关键字参数
(1) def func(a,b,*,c,d)跟在*号后面的c和d
(2) def func(*args,e,**kwargs)加在*args和**kwargs之间的参数都是命名关键字参数
命名关键字参数:在调用函数时,必须使用关键字实参的形式来进行调用
"""
# 定义方法一:
def func(a, b, *, c, d):
print(a, b) # 1 2
print(c, d) # 3 4
# 必须指定关键字实参,才能对命名关键字形参进行赋值
func(1, 2, c=3, d=4)
# 定义方法二:
def func(*args, e, **kwargs):
print(args) # (1, 2, 3, 4)
print(e) # 3
print(kwargs) # {'a': 1, 'b': 2}
func(1, 2, 3, 4, a=1, b=2, e=3)
"""
# 星号的使用
* 和 **如果在函数的定义处使用
* 把多余的普通实参打包成元组
** 把多余的关键字实参打包成字典
* 和 **如果在函数的调用处使用
* 把元组或者列表进行解包
** 把字典进行解包
"""
def func(a, b, *, c, d):
print(a, b)
print(c, d)
tup = (1, 2)
# 函数的调用处 *号用法
func(*tup, c=3, d=4)
# 函数的调用处**号用法
dic = {"c": 3, "d": 4}
# func = (1,2,**dic)
# 综合写法
# 函数的调用处
tup = (1, 2)
dic = {"c": 3, "d": 4}
func(*tup, **dic)
# 定义成如下形式,可以收集所有的实参
def func(*args, **kwargs):
pass
"""
总结:当所有的形参都放在一起,顺序原则:
普通形参 -> 默认形参 ->普通收集形参 -> 命名关键字形参 -> 关键字收集形参
"""
def f1(a, b, c=0, *args, **kw):
print('a=', a, 'b=', b, 'c=', c, 'args=', args, 'kw=', kw)
def f2(a, b, c=0, *,d ,**kw):
print("a=", a, "b=", b, "c=", c,"d=",d , "kw=", kw)
# 以上俩个函数 打印结果
# (一)
f1(1, 2) # a= 1 b= 2 c= 0 args= () kw= {}
f1(1, 2, c=3) # a= 1 b= 2 c= 3 args= () kw= {}
f1(1, 2, 3) # a= 1 b= 2 c= 3 args= () kw= {}
f1(1, 2, 3, "a", "b", x=99) # a= 1 b= 2 c= 3 args= ('a', 'b') kw= {'x': 99}
f2(1, 2, d=99, ext=None) # a= 1 b= 2 c= 0 d=99 kw= {'ext': None}
# (二)
args = (1, 2, 3, 4)
kw = {"d": 1, "b1": 3}
f1(*args, **kw) # a= 1 b= 2 c= 3 args= (4,) kw= {'d': 1, 'b1': 3}
# (三)
args = (1, 2, 3)
kw = {"d": 88, "x": "#"}
f2(*args, **kw)
7.1.4 return 返回值
-
概念: return 把函数内部的数据返回到函数的外面,返回到函数的调用处
-
作用:
(1) return 六大标准数据类型,除此之外还可以返回函数,或者是对象
(2) return 在执行时,意味着终止函数,后面的代码不执行
(3) 如果不定义return返回值,默认返回None
# (1) return 六大标准数据类型 def func(): # return 111 # return 6.89 # return "你好" # return [1,2,3] # return {"a":1,"b":2} return 1,2,3 #返回元组 res = func() print(res) # (2)终止函数,后面的代码不执行 def func(): for i in range(5): if i == 3: return 4 print(i) res = func() print(res) # (3)如果不定义return返回值,默认返回None def func(): pass res = func() print(res) #None # (4)注意:打印的数据和返回值的数据不是等价的,返回的数据是可以自定义的 res = print(1234) print(res) def func(): print(1234) res = func() print(res) #None # (5)练习:模拟器+-*/计算器 """ 功能:完成计算 参数: 2个数和运算符 返回值: 计算后的结果 """ def calc(num1,num2,sign): if sign == "+": return num1 + num2 elif sign == "-": return num1 - num2 elif sign == "*": return num1 * num2 elif sign == "/": if num2 == 0: return "除数不能为零" return num1 / num2 res = calc(3,5,"+") res = calc(3,5,"-") res = calc(3,5,"*") res = calc(1,0,"/") print(res)
7.2 函数小高级
- python中的函数可以像变量一样,动态创建,销毁,
- 可以当做参数传递,
- 可以作为值返回,叫第一类对象,其他语言功能有限
7.2.1 函数动态创建与销毁
def func():
print("我是func函数")
# (1)动态创建
a = 1
print(a)
a = func
a()
# (2) 动态销毁
del a
# a()
# func()
7.2.2 函数当作参数传递
def func2():
return "我是func2函数"
def func1(f):
return f() #"我是func2函数"
res = func1(func2)
print(res)
7.2.3 函数当作值返回
def func3():
print("我是func3函数")
def func4(f):
return f
res = func4(func3)
print(res)
res()
7.2.4 函数名当作容器类型数据的元素
def func1():
print(111)
def func2():
print(222)
lst = [func1,func2]
for i in lst:
i()
# __doc__或者help查看文档(双下划线)
def big_chang_cishen(something):
"""
功能:教你怎么吃大肠
参数:吃的内容
返回值:是否满意
"""
print("把这个肠子洗洗")
print("直接找肠子头,放嘴里,吸一下")
print("擦擦嘴,满意的放下肠子头")
return "吃完了,真好吃"
big_chang_cishen("生肠子")
# 方法一
res = big_chang_cishen.__doc__
print(res)
# 方法二
help(big_chang_cishen)
7.2.5 匿名函数:lambda表达式
-
作用: 用一句话来表达只有返回值的函数,简洁与高效
-
语法:lambda 参数: 返回值
# (1)无参的lambda表达式 def func(): return "文哥是个帅哥" # 改造 func = lambda:"alex" print(func()) # (2) 有参的lambda表达式 def func(n): return id(n) # 改造 func = lambda n: id(n) print(func(100)) # (3) 带有判断条件的lambda表达式 def func(n): if n % 2 == 0: return "偶数" else: return "奇数" # 三元运算符 """ 语法:真值 if 条件表达式else 假值 如果条件表达式成立为Ture,返回if前面的真值,反之,返回else后面的假值 """ n = 13 res = "偶数"if n%2 == 0 else "奇数" print(res) # 小练习 比较两者之间的最大值进行返回 def func(x,y): if x > y: return x else: return y print(func(1,2)) # 改造 func = lambda x,y: x if x > y else y print(func(40,30))
7.3 函数中高级
7.3.1 函数的嵌套
-
形式: 互相嵌套的两个函数 包裹在外层叫做函数,内层的就是内函数
-
LEGB原则(就近找变量原则):
找寻变量的调用顺序采用LEGB原则(即就近原则)
B - Builtin(python);python内置模块的命名空间(内建作用域)
G - Global(module);函数外部所在的命名空间(全局作用域)
E - Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L - Local(function):当前函数内的作用域(局部作用域) 依据就近原则,从下往上 从里向外 依次寻找
def outer(): def inner(): print("我是inner函数") inner() # (1)内部函数可以直接在函数外部调用吗? 不行 inner() # (2)调用外部函数后,内部函数可以在函数外部调用吗? 不行 outer() inner() # (3)内部函数可以在函数内部调用吗? 可以 outer() # (4)内部函数在函数内部调用时,是否有先后顺序? 有的 # 先定义在调用 # 在其他语言中有预加载的机制,提前把函数驻留在内存中,然后再去编译脚本内容 # python没有预加载函数的机制,只能先定义在调用 # 外函数是outer 中间函数是inner 最里层是smaller,调用smaller函数 def outer(): def inner(): def smaller(): print("我是smalller函数") smaller() inner() outer() def outer(): def inner(): def smaller(): print(id) smaller() inner() outer()
7.3.2 闭包函数
-
概念: 互相嵌套的两个函数,内函数使用了外函数的局部变量 ,并且外函数把内函数返回出来的过程,叫做闭包 里面的函数叫做闭包函数
-
判断是不是闭包: 内函数使用了外函数的局部变量 ,外函数返回内函数
# 1.基本语法 def xiaoming_family(): father = "马云" def hobby(): print("我对钱没有一丝丝的兴趣,我不看重钱这是我爸爸{}说的".format(father)) return hobby func = xiaoming_family() func() tup = func.__closure__ print(tup[0].cell_contents) print(tup) # 2.闭包的复杂形式 def xiaohong_family(): gege = "王思聪" didi = "高振宇" money = 1000 def gege_hobby(): nonlocal money money -= 500 print("我交朋友不在乎他有钱,钱还剩下{}".format(money)) def didi_hobby(): nonlocal money money -= 400 print("家里有鞋柜,一双大概20~30万,钱物还剩下{}".format(money)) def big_master(): return [gege_hobby, didi_hobby] return big_master func = xiaohong_family() print(func) lst = func() print(lst) # 获取哥哥函数 gege = lst[0] gege() # 获取弟弟函数 didi = lst[1] didi() # 3.使用__closure__,cell_contents判定闭包 """如果返回的元组中有数据说明是闭包,谁的生命周期被延长就打印谁""" tup = func.__closure__ print(tup) # 先获取第一个单元格 cell_contents获取对象中的内容 func1 = tup[0].cell_contents func1() # 再获取第二个单元格 cell_contents获取对象中的内容 func2 = tup[1].cell_contents func2() def func(): print(1) func() print(133) var = id(123) # #### 闭包特点 """ 特点:在闭包函数中,内函数使用了外函数的局部变量 该变量会与内函数发生绑定,延长该变量的生命周期 持续到脚本执行结束 """ def outer(val): def inner(num): return val + num return inner func = outer(10) res = func(15) print(res) # ### 闭包的意义 num = 0 def click_num(): global num num += 1 print(num) click_num() click_num() click_num() num = 100 click_num() click_num() # 改造,用闭包来实现 def outer(): x = 0 def click_num(): nonlocal x x += 1 print(x) return func = outer() print(func)
7.4 作用域
-
概念:
(1) 局部变量: 在函数内部定义的变量就是局部变量
(2) 全局变量: 在函数外部定义的变量或者在函数内部使用global关键字声明是全部变量
-
作用域: 局部变量的作用范围仅仅在函数的内部 全局变量的作用范围横跨整个文件
-
生命周期: 该变量的作用时长
内置命名空间 -> 全局命名空间 -> 局部命名空间(调用函数时,该局部变量会被创建,函数执行结束时,该局部变量会被立刻释放掉) 内置属性 > 全局属性 > 局部属性(从长到短)
# 1.局部变量 def func(): # 定义一个局部变量 a = 1 # 获取当前的局部变量 print(a) # 修改一个局部变量 a = 2 func() # print(a) error报错 # 2.全局变量 # 定义一个全局变量 b = 10 # 获取当前的全局变量 print(b) b = 20 # 修改一个全局变量 print(b) def func(): print(b) func()
7.4.1 global的使用
-
如果当前不存在全局变量,可以在函数内部通过global关键字来定义全局变量
-
如果当前存在全局变量,可以在函数内部通过global关键字来修改全局变量
-
用来修改全局变量
# 1.函数内部定义全局变量 def func(): global c c = 30 func() print(c) # 2.函数内部修改全局变量 d = 50 def func(): global d d = 51 func() print(d)
7.4.2 nonlocal的使用
- 遵循LEGB原则
- 他会找当前空间上一层的变量进行修改
- 如果上一层空间没有,继续向上找寻找
- 如果最后找不到,直接报错
- 用来修改局部变量
# (1)他会找当前空间上一层的变量进行修改 def outer(): a = 10 def inner(): nonlocal a a = 20 print(a) inner() print(a) outer() # (2) 如果上一层空间没有,继续向上寻找 def outer(): a = 20 def inner(): def smaller(): nonlocal a a = 30 print(a) smaller print(a) inner() print(a) outer() # (3)如果最后找不到,直接报错 a = 20 def outer(): def inner(): def smaller(): nonlocal a a = 30 print(a) smaller print(a) inner() print(a) outer() # (4) 不通过nonlocal是否可以修改局部变量呢? def outer(): lst = [1,2,3] def inner(): lst[-1] = 3000 inner() print(lst) outer()
7.4.3 locals globals 其它使用
# ### locals globals使用(了解)
# locals 获取当前作用域所有的变量
# 1.全局空间
"""
locals 在函数外,获取的是打印之前所有的全局变量
locals 在函数内,获取的是调用之前所有的局部变量
"""
def func():
a1 = 1
b2 = 2
a = 1
b = 2
res = locals()
c = 3
print(res)
d = 4
# 2. 局部空间
a = 1
b = 2
def func():
a1 = 1
b2 = 2
res = locals()
c3 = 3
print(res)
d4 = 4
c = 3
func()
d = 4
# globals
"""
globals在函数外,获取的是打印之前所有的全局变量
locals在函数内,获取的是调用之前所有的局部变量
"""
# 1.全局空间
"""
def func():
a1 = 1
b2 = 2
a = 1
b = 2
res = globals()
c = 3
print(res)
d = 4
"""
# 2.局部空间
"""
a = 1
b = 2
def func():
a1 = 1
b2 = 2
res = globals()
c3 = 3
print(res)
d4 = 4
c = 3
func() globals()
d = 4
"""
# ### globals 返回的是内置系统的全局字典
"""
res = globals()
print(dict)
dic['wangwen'] = "18岁"
print(wangwen)
"""
# 批量创建全局变量
def func():
dic = globals()
for i in range(1,5):
# 批量在dic当中添加键值对,以创建全局变量
dic ["a%d"%(i)] = i
"""
dic["a1"] = 1
dic["a2"] = 2
dic["a3"] = 3
dic["a4"] = 4
"""
func()
print(a1,a2,a3,a4)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix