函数进阶
1. 名称空间的作用域
作用域:名称空间所能够作用的范围
- 内置名称空间
程序任何阶段,任何位置,均可使用 - 全局名称空间
程序任何阶段,任何位置,均可使用 - 局部名称空间
一般只在各自的局部名称空间中有效
2. global 与 nonlocal关键字使用
-
global关键字
x = 111 def index(): # 局部修改全局变量,需要使用关键字声明 global x x = 222 index() print(x) # 222
# 在局部想要修改可变类型,不需要global关键字 name_list = ['josh', 'duke'] def index(): name_list.append('kd') index() print(name_list) # ['josh', 'duke', 'kd']
如果:想要在局部修改全局数据
- 如果数据为不可变类型,则需要关键字global声明。
- 如果数据为可变类型,则无需关键字global声明。
-
nonlocal关键字
def index(): x = 11 def func(): x = 22 func() print(x) index() # 11
def index(): x = 11 def func(): # 内部局部修改外部局部 nonlocal x x = 22 func() print(x) index() # 22
如果:想在内部局部修改外部局部数据
- 如果数据为不可变类型,则需要关键字nonlocal声明。
- 如果数据为可变类型,则无需关键字nonlocal声明。
3. 函数对象(函数名)
函数名主要由四种用法。。
-
用法一:函数名可以当作变量名赋值
def index(): print('from index') # print(index) # 函数名就是一个内存地址 a = index # a就函数名,函数名遇到括号就会调用 a() # from index # 本质就是在调用index函数
-
用法二:函数名还可以当作函数的实参
def index(): print('from index') def func(a): print(a) print('from func') func(index) """
from func""" -
用法三:函数名可以当作函数的返回值
def index(): print('from index') return index res = func() # 调用func并接收其返回值 print(res) # 函数index res() # 执行函数index >>> from index
-
用法四:函数名可以当作容器类型(内部可以存放多个数据)的元素
def index(): print('from index') l = [1, 2, 3, index] print(l) """[11, 22, 33,
]""" l1 = [1, 2, 3, index()] print(l1) """from index [11, 22, 33, None]"""
4. 函数的嵌套调用
嵌套调用:函数内部调用其他函数。
def index():
func()
print('from index')
def func():
index()
print('from func')
func() # 层数过多,一直循环,报错。
def my_max(a, b):
if a > b:
return a
return b
def many_max(x, y, z, c):
# 所谓的白嫖主义
res = my_max(x, y)
res1 = my_max(res, z)
res2 = my_maz(res1, c)
return res2
ret = many_max(12, 33, 55, 78)
print(ret) # 78
5. 函数的嵌套定义
函数嵌套定义:函数体内部定义其他函数
def index():
name = 'joshua'
def func(): # 函数内部定义其他函数
print('from func')
index()
"""
应用场景:
将复杂的功能全部隐藏起来,暴露一个简单的接口。
"""
def all_func(choice):
def register():
print('注册功能')
def login():
print('登录功能')
def transfer():
print('转账功能')
def shopping():
print('购物功能')
if choice == '1':
register()
if choice == '2':
login()
...
...
# 在以上类似的场景中可以用到函数嵌套定义。
6. 闭包函数(重点-不难)
闭:定义在函数内部的函数。
包:内部函数引用了外部函数名称空间中的名字。
只有符合上述 两个 特征的函数才可以称为“闭包函数”。
注意:
def outer():
def index():
print('from index', x)
return index
res = outer()
x = 33
res() # from index 33
# 此函数没有引用外部函数名称空间中的名字,
# 故,不是闭包函数。
-
闭包函数其实是给函数传参的第二种方式
# 传参方式一:函数体代码需要用到数据,直接在括号内定义即可。 def my_max(a, b): if a > b: return a return b # 方式二:利用闭包函数 def outer(x, y): def my_max(): if x > y: return x return y return my_max res = outer(22, 56) print(res()) # 56
-
闭包的实际应用
import requests # 爬取百度首页数据 def outer(url): def get_content(): res = requests.get(url) if res.status_code == 200: with open(r'xxx.html','rb') as f: f.write(res.content) return get_content res = outer('https://www.baidu.com') res() res() ...
闭包的作用:
- 可以给函数体传参
- 让内部函数参数不受外部的影响。
7. 装饰器的概念
-
什么是装饰器???
器:指工具。
装饰:给被装饰对象添加额外的功能。 -
装饰器的原则
开放封闭原则
开放:对扩展开放
封闭:对修改封闭 -
装饰器核心思想
在 不改变被装饰对象内部代码 和 原有调用方式 的基础上,添加额外的功能。
"""
装饰器并不是一个新知识
而是由之前学的:名称空间,函数对象,闭包函数组合而来的。
"""
# def index():
# print('from index')
# index()
# 统计index函数的执行时间
import time
print(time.time()) # 获取的结果是时间戳,
# (运行代码的那一刻距离1970-1-1所经历的秒数)
time.sleep(3) # 让程序原地阻塞 3 秒
def index():
print('from index')
time.sleep(2)
start_time = time.time()
index()
end_time = time.time()
print(end_time - start_time)