python闭包及装饰器

一、闭包

闭包的概念:一个完整的闭包必须满足三个条件:

(1)函数中嵌套一个函数

(2)外层函数返回内层函数的变量名

(3)内层函数对外部作用域有一个非全局的变量进行引用

最简单的闭包案例:

def outer():
    x=100
    def inner():
        y=x*2
        print(y)
    return  inner

print(outer()) #运行结果:<function outer.<locals>.inner at 0x110d3ab70>
outer()()  #运行结果:打印200

二、装饰器

python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象。

1、装饰器结构

def w1(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        return func()
    return inner
 
@w1
def f1():
    print 'f1'

2、函数装饰器

1)函数不带参数

#函数装饰器-函数不带参数
import time
def runtime(func):
    def wrapper():
        start = time.time()
        f = func()     # 原函数
        end = time.time()
        print("运行时长:%.4f 秒" % (end-start))
        return f
    return wrapper

@runtime
def func_a():
    print("func_a")
    time.sleep(0.5)

@runtime
def func_b():
    print("func_b")
    time.sleep(0.8)

if __name__ == '__main__':
    func_a()
    func_b()

 

2)函数带参数

#函数装饰器-函数带参数
import time
def runtime(func):
    def wrapper(*args,**kwargs):
        start = time.time()
        f = func(*args,**kwargs)     # 原函数
        end = time.time()
        print("运行时长:%.4f 秒" % (end-start))
        return f
    return wrapper

@runtime
def func_a(a):
    print("func_a")
    print("a="+a)
    time.sleep(0.5)

@runtime
def func_b(b,c="3"):
    print("func_b")
    print("b="+b)
    print("c="+c)
    time.sleep(0.8)

if __name__ == '__main__':
    func_a("1")
    func_b("2")

3)装饰器带参数

#函数装饰器-装饰器带参数
import time
def runtime(slowly=1):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            start = time.time()
            f = func(*args, **kwargs)     # 原函数
            end = time.time()
            t = end-start
            print("运行时长:%.4f秒"%t)
            time.sleep(slowly)  # 延迟效果
            new_end = time.time()
            print("延时时长:%.4f 秒" % (new_end-start))
            return f
        return inner_wrapper
    return wrapper

@runtime(1.5)
def func_a(a):
    print("a="+a)
    time.sleep(0.5)

@runtime(0.5)
def func_b(b, c="c"):
    print("b="+b)
    print("c="+c)
    time.sleep(0.8)

if __name__ == '__main__':
    func_a("a")
    func_b("b", c="c")

 3、类装饰器

1)装饰器不带参数

#类装饰器-装饰器带参数
import time
class runtime:
    def __call__(self, func):
        def inner_wrapper(*args, **kwargs):
            start = time.time()
            f = func(*args, **kwargs)     # 原函数
            end = time.time()
            t = end-start
            print("运行时长:%.4f秒"%t)
            return f
        return inner_wrapper

@runtime()
def func_a(a):
    print("a="+a)
    time.sleep(0.5)

@runtime()
def func_b(b, c="c"):
    print("b="+b)
    print("c="+c)
    time.sleep(0.8)

if __name__ == '__main__':
    func_a("a")
    func_b("b", c="c")

2)装饰器带参数

#类装饰器-装饰器带参数
import time
class runtime:
    def  __init__(self,slowly=1):
        self.slowly=slowly
    def __call__(self, func):
        def inner_wrapper(*args, **kwargs):
            start = time.time()
            f = func(*args, **kwargs)     # 原函数
            end = time.time()
            t = end-start
            print("运行时长:%.4f秒"%t)
            time.sleep(self.slowly)  # 延迟效果
            new_end = time.time()
            print("延时时长:%.4f 秒" % (new_end-start))
            return f
        return inner_wrapper
    
@runtime(1.5)
def func_a(a):
    print("a="+a)
    time.sleep(0.5)

@runtime(0.5)
def func_b(b, c="c"):
    print("b="+b)
    print("c="+c)
    time.sleep(0.8)

if __name__ == '__main__':
    func_a("a")
    func_b("b", c="c")

4、内置装饰器

class MyTest(object):
    def __init__(self,name):
        self.name=name

    @classmethod
    def class_method(cls):   #被classmethod装饰了之后,该方法就是一个类方法
        print('这是类方法')  #cls代表的是类本身
        print(cls)

    @staticmethod
    def static():
        print("这是静态方法")

    @property
    def read_property(self): #设定只读属性
        print("装饰器装饰完后,该方法变成只读属性")
        return "18"

    def sub(self): #普通实例方法
        print("sub中的self",self)

m=MyTest("test")
m.class_method()
MyTest.class_method()
print("-----------------")
m.static()
MyTest.static()
print("-------------------")
print("打印只读属性:"+m.read_property)
print("----------------")
m.sub()

运行结果:

这是类方法
<class '__main__.MyTest'>
这是类方法
<class '__main__.MyTest'>
-----------------
这是静态方法
这是静态方法
-------------------
装饰器装饰完后,该方法变成只读属性
打印只读属性:18
----------------
sub中的self <__main__.MyTest object at 0x109c899e8>

 

文章内容参考自上海-悠悠:https://www.cnblogs.com/yoyoketang/p/10801242.html

posted on 2020-04-30 16:28  crystal1126  阅读(215)  评论(0编辑  收藏  举报

导航