一、变量的作用域链
# -*- coding:utf-8 -*-
a = 10
def func1():
b = 20
def func2():
c = 30
return a + b + c
return func2()
print(func1())
二、利用闭包突破作用域链
# -*- coding:utf-8 -*-
'''闭包
概念:在函数体重定义内部函数,并且使用了外部函数的变量,然后把内部函数给,那么这个内部函数就是闭包
优点:避免污染全局环境,这样就可以在函数体外使用函数体中定义的变量
缺点:数据长期驻留在内存中,造成内存极大的浪费。
'''
a = 10
def func1():
b = 20
def func2():
c = 30
return a
return func2
f2 = func1()
print(f2())
def func3():
b = 40
def func4():
return b
return func4
三、装饰器概念
# -*- coding:utf-8 -*-
'''
是一个闭包,把一个函数作为参数然后返回一个替代版函数,本质上就是一个返回函数的函数
'''
#在不修改原函数的前提下增加函数的功能,最好的方式是使用装饰器
def func():
print("Martin is a good man")
def f():
print("***********")
func()
四、简单装饰器
# -*- coding:utf-8 -*-
def func():
print("sunck is a good man")
def wrapper(f):
def inner():
print("***********")
f()
return inner
# d = wrapper(func)
# d()
func = wrapper(func)
func()
五、复杂装饰器
# -*- coding:utf-8 -*-
# 下不修改say原函数代码的情况下增加say的功能,判断age是否符合常理
def say(name, age):
return "%s is a good man! he is %d years old"%(name, age)
def wrapper(f):
def inner(name, age):
#增加功能
if age <= 0:
age = 0
return f(name, age)
return inner
say = wrapper(say)
print(say("Martin", -18))
六、使用@符号装饰
# -*- coding:utf-8 -*-
'''
python2.4支持使用@将装饰器应用在函数上,只需要再函数定义前加上@装饰器的名称即可
'''
def wrapper(f):
def inner(name, age):
#增加功能
if age <= 0:
age = 0
return f(name, age)
return inner
@wrapper
def say(name, age):
return "%s is a good man! he is %d years old"%(name, age)
# 相当于 say = wrapper(say)
print(say("Martin", -18))
七、通用装饰器
# -*- coding:utf-8 -*-
def wrapper(f):
def inner(*args, **kwargs):
#在这增加功能
print("no zuo no die")
res = f(*args, **kwargs)
#如果要修改原函数的返回值,在这修改
return res
return inner
@wrapper
def func(name, age):
print(name, age)
return "Martin is a good man"
print(func("kaige", 17))
@wrapper
def func2(height):
print(height)
print("**********")
func2(111)
八、参数的装饰器
# -*- coding:utf-8 -*-
def wrapper(count=3):
def deco(f):
def inner(*args, **kwargs):
for i in range(count):
f(*args, **kwargs)
return inner
return deco
@wrapper()
def func():
print("Martin is a good man")
func()
九、计算程序运行时间
# -*- coding:utf-8 -*-
import time
def timer(f):
def inner(*args, **kwargs):
time1 = time.time()
res = f()
time2 = time.time()
print("程序运行:%f"%(time2-time1))
return res
return inner
@timer
def func():
print("Martin is a nice man")
time.sleep(2)
print("Martin is a good man")
func()
十、多个装饰器
# -*- coding:utf-8 -*-
def wrapper1(f):
print("enter wrapper1")
def inner1(*args, **kwargs):
print("enter inner1")
res = f(*args, **kwargs)
print("exit inner1")
return res
print("exit wrapper1")
return inner1
def wrapper2(f):
print("enter wrapper2")
def inner2(*args, **kwargs):
print("enter inner2")
res = f(*args, **kwargs)
print("exit inner2")
return res
print("exit wrapper2")
return inner2
def wrapper3(f):
print("enter wrapper3")
def inner3(*args, **kwargs):
print("enter inner3")
res = f(*args, **kwargs)
print("exit inner3")
return res
print("exit wrapper3")
return inner3
'''
装饰时:从距离近的装饰器开始装饰
执行时:从距离远的装饰器内部函数开始执行
'''
@wrapper1
@wrapper2
@wrapper3
def func(x, y):
return x + y
print("----------------")
func(1, 2)
'''
inner3 = wrapper3(func)
inner2 = wrapper2(inner3)
inner1 = wrapper1(inner2)
func = inner1
'''
十一、装饰器使用场景
# -*- coding:utf-8 -*-
count = 0
'''
1、参数、结果检查
2、缓存
3、计数
4、日志
5、统计
6、权限管理
7、重试
'''
十二、计数函数执行次数
# -*- coding:utf-8 -*-
def count(f):
index = 0
def inner(*args, **kwargs):
nonlocal index
index += 1
res = f(*args, **kwargs)
print("第%d次执行"%index)
return res
return inner
@count
def func():
print("Martin is a good man")
@count
def func1():
print("Martin is a nice man")
func()
func()
func1()
func()
func1()
十三、retry装饰器
# -*- coding:utf-8 -*-
def retry(count=3, wait=0,exceptions=(Exception,)):
import time
def wrapper(f):
def inner(*args, **kwargs):
for i in range(count):
try:
print("-------------------")
res = f(*args, **kwargs)
except exceptions as e:
time.sleep(wait)
continue
else:
return res
return inner
return wrapper
import random
@retry(5)
def connetSQL(ip, port, dbName, passwd):
num = random.choice([1,2,3,4])
print("**************", num)
if num <= 4:
10 / 0
connetSQL("", "", "", "")
————————————————
版权声明:本文为【PythonJsGo】博主的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
博主主页:https://my.oschina.net/u/3375733
本篇文章同步在个人公众号: