目录
一,全局变量,局部变量,自由变量的区别
global_var = 100 # 写在模块里的变量称为全局变量
def outer():
external_var = 99 # 写在函数里边的称为局部变量,因为他属于outer函数栈区
def inner():
local_var = external_var # 在内部函数里本地变量local_var引用了外部函数的external_var变量
print(local_var)
return inner
inn = outer() # 这里变量inn接收了内部函数inner,inner函数又引用了external_var变量,这时external_var就成了一个自由变量
inn()
# 显示99
二,闭包的概念
闭包就是一个把自由变量封闭起来的包,其实就是一个内部函数把外部函数的变量给闭起来给自己用。上面代码中,内部函数inner把外部函数的external_var变量给引用了。然后把内部函数inner以及自由变量external_var打包返回给变量inn。当outer函数执行完毕,external_var变量本应该被回收,但是嵌套函数(内部函数)inner仍然能使用external_var,并且打印出来external_var的值99。
像这样,本身没有定义一个变量(inner内部函数并没有定义external_var),但是却使用了它(inner函数引用了external_var),并且将函数自身与自由变量打包返回,则称这个返回的函数为闭包。上面代码中inner就是一个闭包,同时inn变量又指向了内部函数inner,实现了变量inn与内部函数innner的绑定。
三,函数是一等公民,函数名可以作为参数
在python中,函数名是一个变量,可以作为另一个函数的参数。并且通过在变量名后面加上英文括号()来执行。比如inn指向的是闭包inner,inn()就是执行了该闭包。
四,将一个函数对象闭起来
在上面的代码中,嵌套函数inner把外部变量external_var给闭起来给自己用,很明显external_var是一个整数类型,那么可不可以把一个函数类型给闭起来呢?答案是可以的。看下面的代码。
def test():
print('我将会被嵌套函数给闭起来')
def outer(func):
def inner():
func_copy = func # 在内部函数里引用了外部变量func,而func指向的是test函数,inner把func/test给闭起来了
func_copy() # 执行func_copy,其实就是执行了test函数
return inner
inn = outer(test) # 这里把函数名test作为参数传递给了outer函数
inn()
# 我将会被嵌套函数给闭起来
五,详解装饰器
理解装饰器的概念,首先要弄清楚装饰器是用来干什么的。装饰器的作用就是在不修改一个函数的前提下,给这个函数增加新的功能(我们都知道一般一个函数只实现一个功能)。怎么来实现这个目的呢?有一个方法就是使用闭包来实现,从而得到一个增加了新功能的函数。
def decoration(func):
def wrapper():
func_copy = func
print('在被修饰函数执行前先执行一些其他功能')
func_copy()
print('在被修饰函数执行后在执行一些其他功能')
return wrapper
# old_func将要增加新功能,他将要被装饰
def old_func():
print('我是需要增加功能的函数')
old_func() # 被装饰之前先看看自己长什么样
# 打印出:我是需要增加功能的函数
# 我是old_func函数,我用下面的代码来装饰自己,但是我自身功能不会改变,所以还是用我原来的名字来绑定被装饰的自己
old_func = decoration(old_func)
old_func() # 我已经被装饰了,运行一下看看
# 打印出下面的内容
# 在被修饰函数执行前先执行一些其他功能
# 我是需要增加功能的函数
# 在被修饰函数执行后在执行一些其他功能
当然也可以采用语法糖的形式来实现函数的装饰。
def decoration(func):
def wrapper():
func_copy = func
print('在被修饰函数执行前先执行一些其他功能') # 需要装饰的内容代码写在这里,也可以接受其他函数在这里执行
func_copy()
print('在被修饰函数执行后再执行一些其他功能')
return wrapper
# old_func将要增加新功能,他将要被装饰,这次使用@decoration来装饰自己
@decoration
def old_func():
print('我是需要增加功能的函数')
# @decoration等价于执行old_func = decoration(old_func)这句代码
old_func() # 我已经被装饰了,运行一下看看
# 打印出下面的内容
# 在被修饰函数执行前先执行一些其他功能
# 我是需要增加功能的函数
# 在被修饰函数执行后在执行一些其他功能
以上就是装饰器基本的使用方法,不足之处请大家指出。