python-函数\作用域\闭包
1、拆包补充,首先先看一段代码:
def func(*args, **kwargs): print(args) print(kwargs) list1 = [1, 2, 3, 4, 6, 8] func(list1, 100) #([1, 2, 3, 4, 6, 8], 100) {} func(*list1, 100) # (1, 2, 3, 4, 6, 8, 100) {} func(*list1, 100, a=1) # (1, 2, 3, 4, 6, 8, 100) {'a': 1} dict1 = {'a': 10, 'b': 20, 'c': 30} func(list1, 100, dict1) # ([1, 2, 3, 4, 6, 8], 100, {'a': 10, 'b': 20, 'c': 30}) # {} func(*list1, 100, dict1) # (1, 2, 3, 4, 6, 8, 100, {'a': 10, 'b': 20, 'c': 30}) # {} func(*list1, 100, **dict1) # (1, 2, 3, 4, 6, 8, 100) # {'a': 10, 'b': 20, 'c': 30}
**dict1 在函数调用的时候表示拆包,会将字典中内容拆成关键字参数的形式
def func(a,b,c): list1 = [a,b,c] print(list1) dict1={'a':10,'b':20,'c':30} func(**dict1) # [10, 20, 30]
2、函数之间的调用
books = ['红楼梦','西游记','水浒传','三国演义'] def show_books(): print('-----图书馆书籍如下:-------') for index,book in enumerate(books): print('{}:{}'.format(index+1,book)) def add_books(book_name): if book_name: books.append(book_name) # 确认是否成功 show_books() print('添加成功') else: print('书籍不能为空!') # 添加图书 add_books('斗破苍穹')
3、返回值:
1》如果函数没有返回值则默认的返回值是None
2》如果在函数中添加返回值,要通过return关键字
return关键字的作用:
1-返回return后面值
2-结束方法(函数)
break ---结束循环
return----出现在函数,表示结束函数
3-return可以单独使用,返回值是None
python独有的
return a,b,c ------ (a,b,c)
补:return后面可以是一个参数 接收的的时候x = add(1,2)
return后面也可以是多个参数,如果是多个参数则底层会将多个参数先放在一个元组中,将元组作为整体返回。
接收的时候也可以是多个:return 'hello','world' x,y = ('hello','world') x = 'hello' y = 'world'
list1 = [5,5,6,8,9,1] # 找到最大值 def find_max(list1): if isinstance(list1,list): max1 = list1[0] for i in list1: if i >max1: max1=i return max1 m = find_max(list1) print(m)
找到最大值,最大值所在的下标位置。
list1 = [5,5,6,8,9,1] # 找到最大值 def func(list1): if isinstance(list1,list): max1 = list1[0] max_index = 0 for index,i in enumerate(list1): if i >max1: max1=i max_index = index # 返回结果 return max1,max_index m = func(list1) print(m) # (9, 4)
4、函数的作用域:LEGB
local 局部的 函数的本地变量
locals() 在函数中使用,获取的是当前函数的局部变量们,将函数中的局部变量放到字典中
enclosing 嵌套的 两层函数
def func(): a = 10 ------内层函数的enclosing def inner_func(): print(a) inner_func()
global 关键字------ 在函数中对全局变量进行声明而使用的
globals() 用在函数的外层,获取全局的变量(系统的默认产生变量+自定义的变量)
nonlocal 关键字 内层函数中想修改外部函数中变量
builtins 系统内置、所有py文件执行的时候都会加载内置模块
作用域的使用:
全局的:
books[]
number = 10
在函数中使用的时候:
因为books是可变类型,所以可以省略global的声明
因为number是不可变类型,所以在函数中如果想修改则必须添加global的声明
----------------------------------------------------------------------------------------------------------
number = 10 ---》 全局 def func(): number = 0 # 局部变量 print(number) number += 5 ---> 此时只能在局部变量上+5 func() print(number) ---》 10
number = 10 def func(): # 如果想修改全局的变量number,必须要明确声明 global number ----> 明确声明以下使用的number是全局的number print(number) # Unresolved reference 'number' 报错 只有局部变量才有更改“权限”,但是此时number不是局部的 number += 5 func() print(number) ---》 15
number = 10 def func(): global number print(number) ---》10 number = 9 # 相当于对全局变量number=10 的修改 number += 5 func() print(number)---》14
对于可变类型的话:
# 全局变量 books = ['红楼梦', '西游记', '水浒传', '三国演义'] number = 10 def func(): # books = [] books.append('斩龙') # ----> 因为books是可变类型,所以可以省略global的声明 print(books) global number # -----> 因为number是不可变类型,所以在函数中如果想修改则必须添加global的声明 number += 8 func() #['红楼梦', '西游记', '水浒传', '三国演义', '斩龙'] print(books) # ['红楼梦', '西游记', '水浒传', '三国演义', '斩龙'] print(number) # 18
5、搜索变量的规则是:
1》如果有内部函数,先找内部函数自身的变量
2》如果内部函数自身没有变量,则找外部函数的变量
3》如果外部函数也不存在此变量则找全局
4》如果全局也没有此变量则找builtins
5》如果内部builtins也没有则报错
a = 100 b = 0 def func(b): a=10 def inner_func(c): # global b # b = 1 nonlocal b c = a +b +c b = c print('c:',c) print('b:',b) print('a:',a) print('b:',b) inner_func(5) # 调用外部函数 func(8) print(a) print(b)
6、闭包:
1》在一个函数中定义了另一个函数
2》内层函数使用了外层函数的变量
3》返回值是内层函数
闭包的缺点:作用域没有那么直观 因为变量不会被垃圾回收所以会有一定的内存占用问题
闭包作用:1.可以使用同级的作用域 2.读取其他元素的内部变量 3.延长作用域
总结:
闭包优化了变量,原来需要类对象完成的工作,闭包也可以完成。
由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
闭包的好处,使代码简洁,便于阅读代码。
闭包是理解装饰器的基础。
def out_func(n): a = 10 def inner_func(): r = a + n print('r的值:',r) print(locals()) return inner_func result = out_func(2) result() # r的值: 12
7、函数作为参数使用的问题
参数可以是str int bool float list tuple set dict
def A(): print('hello world!') def func2(f): # f = A的地址 print('---->', f) f() print('---->over') func2(A) def func3(f): print('----->start:', f) def inner_func(): print('-----》inner_func') f() print('----->end') return inner_func result = func3(A) print(result) result()
8、装饰器:
功能:1》引入日志 2》函数执行时间统计 3》执行函数前预备处理 4》执行函数后清理功能
5》权限校验等场景 6》缓存
注:写代码要遵循开放封闭的原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,他规定了已经实现的功能代码不允许被修改,但可以被拓展。
开放:对拓展开放
封闭:已实现的功能代码块
# 1、定义函数,闭包的原则+函数作为参数 装饰器函数 def func(f): print('******************1') def wrapper(): print('装饰前。。。。验证是否登录') f() print('装饰后。。。。') print('-----------------2') return wrapper # 2、功能函数 @func # 1.调用func函数 2.执行函数体内容 3.加载内部函数 4.返回内部函数wrapper 5.buy_ticket接收了func的返回值, def buy_ticket(): print('我可以买票去看:雷火英雄') # 3、买票 buy_ticket()
例二:
# 定义装饰器函数 def decorator(func): # func = house def wrapper(): func() # 此时的func就是原house() print('刷漆') print('铺地板') print('买家具') print('可以住.....') return wrapper @decorator def house(): print('空的毛坯房...') house()