1 闭包与装饰器
1.1 闭包
闭包(Closure)是指在一个函数内部定义的函数,并且该内部函数可以访问外部函数作用域中的变量。闭包可以在外部函数执行完毕后,仍然保持对外部函数作用域的引用,从而可以继续访问和操作外部函数作用域中的变量。
闭包需要满足以下三个条件:
外部函数嵌套内部函数
外部函数将内部函数返回
内部函数可以访问外部函数的局部变量
def f1():
print("f1")
i = 0
def f2():
# nonlocal 相当于global 但是nonlocal使用的是外部函数的局部变量
nonlocal i
i += 1
print("f2", i)
return f2
r = f1()
r()
这段代码定义了一个外部函数 f1
,它返回内部函数 f2
的引用。在 f1
内部,我们定义了一个变量 i
并将其初始化为 0
。
内部函数 f2
使用 nonlocal
关键字声明了变量 i
,以便它可以访问和修改 f1
函数作用域中的变量 i
。
当我们调用 f1()
时,它返回了内部函数 f2
的引用,并将外部函数作用域中的变量 i
设置为 0
。我们将这个返回的函数引用赋值给变量 r
。
接下来,我们调用 r()
,实际上是调用了内部函数 f2
。每次调用 r()
,它都会将变量 i
的值加 1
,然后打印出 f2
和当前的 i
值。由于 i
是外部函数作用域中的变量,并且闭包可以保留对外部函数作用域的引用,因此每次调用 r()
都会使用同一个 i
变量。
1.2 装饰器
装饰器(Decorator)是Python中一种用于修改函数或类的行为的特殊语法。装饰器可以在不修改原始函数或类代码的情况下,添加额外的功能或行为。
装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数(也可以是类)。这个新函数通常会包装原始函数,对其进行一些额外的操作,然后返回结果。
装饰器在Python中被广泛应用,可以用于实现日志记录、性能统计、权限验证、缓存等各种功能。它为我们提供了一种优雅而灵活的方式来修改和扩展函数或类的行为。
步骤:
- 定义三个基本函数
- 编写闭包
- 使用闭包加工原始3个函数
- 给闭包添加权限校验
- 函数调用
def login_required(f):
def check():
username = input("请输入用户名")
if username == "admin":
f()
else:
print("用户校验失败")
return check
@login_required
def index():
print("欢迎来到")
index()
@login_required
def cart():
print("欢迎来到购物车")
cart()
@login_required
def mine():
print("欢迎来到我的")
mine()
这段代码定义了一个装饰器函数 login_required
,它接受一个函数 f
作为参数。装饰器函数内部定义了一个新的函数 check
,用于校验用户登录状态。
在每个被装饰的函数之前,我们会调用 login_required
函数,并将被装饰的函数作为参数传递给它,这样就将被装饰的函数替换成了 check
函数。
当我们调用被装饰的函数时,实际上是调用了 check
函数。在 check
函数内部,我们首先要求用户输入用户名,并进行校验。如果用户名为 "admin",则说明用户校验通过,我们会调用原始的被装饰函数 f
;否则,打印出 "用户校验失败"。
通过这样的装饰器机制,我们可以在每次调用被装饰的函数之前进行用户登录的校验。
练习:
随机0-1000以内的500个数字放入列表,使用冒泡排序与选择排序对列表进行升序
编写装饰器 统计 两个方法的时间开销
# 导入模块
import time
import random
# 随机生成500个数
def get_value(n):
l0 = []
for i in range(n):
value = random.randint(0, 1000)
l0.append(value)
return l0
l1 = get_value(500)
# 编写装饰器 统计 两个方法的时间开销
def count(f):
def count_f():
time1 = time.time()
f()
print(time.time() - time1)
return count_f
@count
def bubble():
for i in range(len(l1)):
for j in range(i + 1, len(l1)):
if l1[i] > l1[j]:
l1[i], l1[j] = l1[j], l1[i]
return l1
@count
def select():
for i in range(len(l1)):
min_value = i
for j in range(i + 1, len(l1)):
if l1[j] < l1[min_value]:
min_value = j
l1[i], l1[min_value] = l1[min_value], l1[i]
return l1
bubble()
select()
2 内置函数
2.1 len()求长度
print(len("hello"))
2.2 数学方面
2.2.1 abs 取绝对值
print(abs(-50))
2.2.2 divmod 求整除和余
以元组形式返回,第一个为整除结果,第二个为求余结果
print(divmod(100, 3))
2.2.3 pow 次方
print(pow(2, 3))
2.2.4 round 四舍五入
print(round(3.14))
2.2.5 sum 求和
print(sum(i for i in range(10)))
2.3 all 和any
all 所有元素都是真,结果就是真;如果内容为空,返回真
any 所有元素都是假,结果就是假;如果内容为空,返回假
# 所有元素都为真,结果就是真 如果内容为空结果为真
print(all([10, 1, True]), all([]))
# 有一个为真就为真 如果内容为空就为假
print(any([10, 0, False]), any([]))
2.4 进制转换
(1)bin 十进制转二进制
(2) hex 十进制转十六进制
(3) oct 十进制转八进制
print(bin(10))
print(oct(10))
print(hex(10))
2.5 callable 可调用函数
print(callable(10), callable(lambda x: x))
2.6 ASCII码
- chr 将ASCII码值转字符
- ord 将字符转为ASCII码值
- sorted 按照ASCII码值排序
print(chr(97), ord("A"))
print(sorted("hello world"))
2.7 局部与全局
2.7.1 locals 局部
返回所有局部变量,在函数内部使用
num = 100
s0 = "hello"
def f():
i = 99
result2 = locals()
print(result2)
f()
result = globals()
print(result)
2.7.2 globals 全局
返回全局变量
2.8 输入与输出
(1)input
(2)print
a = input("请输入")
print(a)
2.9 最大与最小
2.9.1 max 最大
2.9.2 min最小
print(max([10,20,30]))
print(max([{"age": 15}, {"age": 5}, {"age": 25}], key=lambda x: x["age"]))
print(min([{"age": 15}, {"age": 5}, {"age": 25}], key=lambda x: x["age"]))
2.10 id 返回对象唯一标识
l0 = [1, 2, 3, 4, 5]
print(id(l0))
2.11 将来要学习的
(1)delattr 删除属性
(2)getattr 获取属性
(3)hasattr 是否有属性
(4)setattr 设置属性