python 闭包与装饰器_Python 闭包与装饰器

一、变量的作用域链

# -*- 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

本篇文章同步在个人公众号:

up-c8d54f6f0a2b9850e7bbdfc70ee7041f808.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值