自己以前整理的笔记,不太完整,后续会不断更新。。。。
一、闭包
闭包三要素:
- 函数嵌套
- 内层函数对外层函数参数的调用
- 外层函数返回内层函数的引用
外层函数可以实现保存其实参数据的功能,以供内层函数使用
返回的内层函数空间中保存着外层函数的所有数据,可以调用
一般用于简单功能的实现,更复杂的功能用函数实现
思考:函数、匿名函数、闭包、对象 当做实参时 有什么区别?
- 匿名函数能够完成基本的简单功能,,,传递是这个函数的引用 只有功能
- 普通函数能够完成较为复杂的功能,,,传递是这个函数的引用 只有功能
- 闭包能够完成较为复杂的功能,,,传递是这个闭包中的函数以及数据,因此传递是功能+数据
- 对象能够完成最为复杂的功能,,,传递是很多数据+很多功能,因此传递是功能+数据
在内层函数中修改外层函数的数据,需要使用nonlocal关键字声明之后,才能修改
并且声明nonlocal后可以实现:类中类属性的作用,能够记录每一次调用内部函数的情况
二、装饰器
需求:在不修改原有代码的前提下,扩展现有功能
效果:类似于类中继承后方法的重写,给父类的方法在原有功能的基础上新增功能
装饰器建立在闭包的基础上,调用被装饰函数时,本质上是调用内层函数,包括传参也通过内层函数实现
所谓实现“重写”的功能,也就是通过内层函数实现的
执行到装饰器时,过程如下:
- 将原函数作为实参传入到装饰器函数中,并将返回值赋值给原函数变量名,即指向装饰器内部函数
- 当再次调用原函数时,实际上调用的是装饰器内部函数
即当解释器执行到装饰器时,自动执行装饰器函数,那么我们只要在装饰器函数中添加功能,就可实现自动操作
# 装饰器原理解析
def outer(fun):
def inner():
print('add function')
fun()
return inner
# outer装饰器
@outer # 解释到这里时自动实现:test= outer(test)
def test():
print('hello')
# 所以这里的test不再是原函数test,而是一个新的test指向inner,同名覆盖
# 这里调用时相当于调用inner()
test()
# 结果:
# add function
# hello
# 装饰器原理分析---自动执行验证
def outer(fun):
# 在自动执行的步骤中添加功能,可实现自动功能
print('-----')
def inner():
print('add function')
fun()
return inner
# python解释器执行到装饰器时,自动执行一步test= outer(test)
@outer
def test():
print('hello')
# 即使这里不调用函数,依然会执行一步
# 结果:
# -----
多个装饰器
多个装饰器装饰一个函数:从下向上装饰
# 装饰器原理分析---多个装饰器
def outer_h(fun):
def inner():
print('---add h---start')
return '<h1>'+fun()+'</h1>'
return inner
def outer_b(fun):
def inner():
print('---add b---start')
return '<b>'+fun()+'</b>'
return inner
# python解释器执行到多个装饰器时,会先执行最底部的装饰器,即先完成一个装饰器获得一个返回的函数inner()
# 再依次向上完成其他装饰器,将返回的函数作为一个新的被装饰函数
@outer_h
@outer_b
def test():
return 'hello world!'
print(test())
# 结果:
# ---add h---start
# ---add b---start
# <h1><b>hello world!</b></h1>
通用装饰器
1.内部函数传参args,*kwargs
2.内部函数有返回值
# 通用装饰器
def outter(fun):
def inner(*args, **kwargs): # 起到中转的作用
print('do something')
return fun(*args, **kwargs) # --->接收原函数test(a,b,c)的参数
return inner
@outter
def test(a,b,c):
print(a+b+c)
test(1,2,3)
带有参数的装饰器
严格遵循装饰器在不修改原代码的前提下,实现同一个装饰器对不同原函数添加不同功能的目的
# *-* coding:utf-8 *-*
# 带参数的装饰器
def shell(temp):
def outter(func):
def inner(*args, **kwargs):
# add something
if temp == 'index':
print('authorise level 1')
elif temp == 'center':
print('authorise level 2')
return func(*args, **kwargs)
return inner
return outter
@shell('index') # 效果:先执行shell()函数,返回outter()函数,再用outter装饰原函数
def index():
print('this is index')
@shell('center')
def center():
print('this is center')
index()
center()
# 结果:
# authorise level 1
# this is index
# authorise level 2
# this is center
类装饰器
# 类装饰器的原理与函数类似
class Test(object):
def __init__(self,func):
self.func=func
def __call__(self, *args, **kwargs):
print('add something')
return self.func()
@Test # 实现类似于test=Test(test)的功能
def test():
print('this is a test')
# 当在实例对象后面加()时,默认调用类中的__call__方法
test()
网友评论