闭包
- 一个内层函数中,引用了外层函数(非全局)的变量,这个内层函数就可以成为闭包。
在Python中,我们可以使用closure来检测函数是否是闭包
闭包就是装饰器的雏形
装饰器
闭包与装饰器示例代码
"""
闭包和装饰器
"""
# 闭包
# 在函数外边调用函数内部的函数
# def func1():
# name = '张三'
#
# def func2():
# print(name) # 能够访问到外层作用域的变量
# func2()
# print(func2.__closure__) # (<cell at 0x1036c7438: str object at 0x10389d088>,)
#
# func1()
# print(func1.__closure__) # None
# def func1():
# name = '张三'
# def func2():
# print(name)
#
# return func2 # 把内部函数当成是返回值返回
#
# ret = func1() # 把返回值赋值给变量ret
# ret() # 调用内部函数
# def print_msg(msg):
# # 这是外层函数
#
# def printer():
# # 这是内层函数
# print(msg)
#
# return printer # 返回内层函数
#
#
# func = print_msg("Hello")
# func()
#
# del print_msg
# func()
# print_msg("hello")
#
# def fun(i):
#
# def func(a):
# return a*i
# return func
# foo = fun(8)
# print(foo(8))
# def create_people():
# print('女娲真厉害,捏个泥吹口气就成了人!')
#
#
# def a(func):
# def b():
# print('洒点水')
# func()
# return b
#
# ret = a(create_people)
# ret()
# def a(func):
# def b():
# print("洒点水")
# func()
# return b
#
# @a
# def create_people():
# print('女娲真厉害,捏个泥吹口气就成了人!')
#
# create_people()
# 装饰带返回值的函数
# def foo(func):
# def bar():
# print("new function")
# r = func()
# return r
# return bar
#
#
# @foo
# def f1():
# return "ok"
#
#
# ret = f1()
# print(ret)
# 装饰带参数的函数
# def foo(func):
# def bar(x, y):
# print("new function")
# func(x, y)
# return bar
#
#
# @foo
# def f1(x, y):
# print("{}+{}={}".format(x, y, x+y))
#
#
# f1(10, 20)
# 带参数的装饰器
# 三层嵌套函数
# def f1():
# def f2():
# name = "Tony"
# def f3():
# print(name)
# return f3
# return f2
#
# f = f1()
# ff = f()
# print(ff())
# 带参数的装饰器函数
# 带参数的装饰器需要定义一个三层的嵌套函数
# def d(name): # d是新添加的最外层函数,为我们原来的装饰器传递参数,name就是我们要传递的函数
# def f1(func): # f1是我们原来的装饰器函数,func是被装饰的函数
# def f2(*arg, **kwargs): # f2是内部函数,*args和**kwargs是被装饰函数的参数
# print(name) # 使用装饰器函数的参数
# func(*arg, **kwargs) # 调用被装饰的函数
# return f2
# return f1
# 带参数的装饰器的完整应用
# def d(a=None):
# def foo(func):
# def bar(*args, **kwargs):
# # 根据装饰器的参数做一些逻辑判断
# if a:
# print("welcome to {} page".format(a))
# else:
# print("welcome to home page")
# # 调用被装饰的函数,接收参数args和kwargs
# func(*args, **kwargs)
# return bar
# return foo
#
#
# @d() # 不给装饰器传参数,使用默认的'None'参数
# def index(name):
# print("hello {}".format(name))
#
#
# @d("电影") # 给装饰器传一个'电影'参数
# def movie(name):
# print("hello {}".format(name))
#
# if __name__ == '__main__':
# index("张三")
# movie("李四")
# 装饰器修复技术
# 被装饰的函数最终都会失去本来的__doc__等信息, Python给我们提供了一个修复被装饰函数的工具。
# from functools import wraps
# def a(func):
# @wraps(func)
# def b():
# print("need some water")
# func()
# return b
#
#
# @a
# def liveing():
# print("to living")
#
#
# liveing()
# print(liveing.__doc__)
# print(liveing.__name__)
# 多个装饰器装饰同一函数
# def foo1(func):
# print("d1")
#
# def inner1():
# print("inner1")
# return "<i>{}</i>".format(func())
#
# return inner1
#
#
# def foo2(func):
# print("d2")
#
# def inner2():
# print("inner2")
# return "<b>{}</b>".format(func())
#
# return inner2
#
#
# @foo1
# @foo2
# def f1():
# return "hello"
#
#
# # f1 = foo2(f1) ==> print("d2") ==> f1 = inner2
# # f1 = foo1(f1) ==> print("d1") ==> f1 = foo1(inner2) ==> inner1
#
# ret = f1() # 调用f1() ==> inner1() ==> <i>inner2()</i> ==> <i><b>inner1()</b></i> ==> <i><b>Hello Andy</b></i>
# print(ret)
#
# '''
# return:
# d2
# d1
# inner1
# inner2
# <i><b>hello</b></i>
# '''
# 类装饰器
# 除了可以使用函数装饰函数外,还可以用类装饰函数。
# class D(object):
# def __init__(self, a=None):
# self.a = a
# self.mode = "装饰"
#
# def __call__(self, *args, **kwargs):
# if self.mode == "装饰":
# self.func = args[0] # 默认第一个参数是被装饰的函数
# self.mode = "调用"
# return self
# # 当self.mode == "调用"时,执行下面的代码(也就是调用使用类装饰的函数时执行)
# if self.a == "调用":
# print("welcome {} page")
# else:
# print("welcome home page")
# self.func(*args, **kwargs)
#
#
# @D()
# def index(name):
# print("Hello {}.".format(name))
#
#
# @D("电影")
# def movie(name):
# print("Hello {}.".format(name))
#
# if __name__ == '__main__':
# index('张三')
# movie('张三')
# 装饰类
# 类装饰器 装饰 类
# 定义一个类装饰器
# class D(object):
# def __call__(self, cls):
# class Inner(cls):
# # 重写被装饰类的f方法
# def f(self):
# print('Hello 张三.')
# return Inner
#
#
# @D()
# class C(object): # 被装饰的类
# # 有一个实例方法
# def f(self):
# print("Hello world.")
#
#
# if __name__ == '__main__':
# c = C()
# c.f()