闭包,装饰器

#闭包python

内层函数对外层函数非全局变量的引用就叫闭包。闭包

判断是否是闭包app

函数名.__closur__函数

返回NONE就不是闭包,返回cell就是闭包测试

闭包的做用spa

当执行一个函数时,若是解释器判断此韩式内部存在闭包,这样python就有一个机制,闭包所在的临时名称空间不会随着函数的执行完毕而关闭设计

def func1():
    name = '老男孩'

    def inner():
        print(name)
    inner()
    print(inner.__closure__)  0x0000000002856E10>

func1()


# <cell at 0x000000000282A768: str object at   闭包

#装饰器blog

第一个版本class

 import  time效率

'''初版本,测试函数low'''
# def login():
#     time.sleep(0.3)
#     print('洗洗更健康...')
#
# def timmer():
#     start_time = time.time()
#     login()
#     end_time = time.time()
#     print('此函数的执行时间%s' % (end_time - start_time))
# timmer()

 

改变了我原来执行函数的执行方式,很差

 def login():
    time.sleep(0.3)
    print('洗洗更健康...')
# login()

def register():
    time.sleep(0.4)
    print('洗洗更健康22222...')
# register()
def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数的执行时间%s' % (end_time - start_time))

timmer(login)
timmer(register)

 

虽然执行函数的方式已经无限接近于原方式,可是更麻烦了,增长了二步代码,改

 

def login():
    time.sleep(0.3)
    print('洗洗更健康...')
# login()

def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数的执行时间%s' % (end_time - start_time))

f1 = login  # 将login函数名给了f1
login = timmer  # 将timmer函数名给了login
login(f1)  # timmer(login)

 

#初级装饰器

 

def login():
    time.sleep(0.3)
    print('洗洗更健康...')
# login()

def timmer(f):  # f = login函数名

    def inner():
        start_time = time.time()
        f()  # login()
        end_time = time.time()
        print('此函数的执行时间%s' % (end_time - start_time))
    return inner

login = timmer(login)  # inner 此login是新变量
login()  # inner()

 

  

 

#简单版装饰器,语法糖

 

def timmer(f):  # f = login函数名
    def inner():
        start_time = time.time()
        f()  # login()
        end_time = time.time()
        print('此函数的执行时间%s' % (end_time - start_time))
    return inner

@timmer  # login = timmer(login)  # inner 此login是新变量   @timmer就是语法糖
def login():
    time.sleep(0.3)
    print('洗洗更健康...')
login()

@timmer  # register = timmer(register)
def register():
    time.sleep(0.2)
    print('洗洗更健康22...')

login()  # inner()

 

 

#被装饰的函数带参数的装饰器

 

def timmer(f):  # f = login函数名
    def inner(*args,**kwargs):  # args (2, 3)
        start_time = time.time()
        f(*args,**kwargs)  # login() *(2, 3) 2,3
        end_time = time.time()
        print('此函数的执行时间%s' % (end_time - start_time))
    return inner

@timmer  # login = timmer(login)  # inner 此login是新变量
def login(a,b):
    print(a,b)
    time.sleep(0.3)
    print('洗洗更健康...')

login(2,3)  # inner(2,3)

 

  

 

#函数带返回值的装饰器(万能装饰器)

 

def timmer(f):  # f = login函数名
    def inner(*args,**kwargs):  # args (2, 3)
        start_time = time.time()
        ret = f(*args,**kwargs)  # login() *(2, 3) 2,3
        end_time = time.time()
        print('此函数的执行时间%s' % (end_time - start_time))
        return ret
    return inner

@timmer  # login = timmer(login)  # inner 此login是新变量
def login(a,b):
    print(a,b)
    time.sleep(0.3)
    print('洗洗更健康...')
    return 666

print(login(2,3))  # inner(2,3)

 

  

 

 

 

def wrapper(f):
def inner(*args,**kwargs):
'''执行被装饰函数以前的操做'''
ret = f(*args,**kwargs)
"""执行被装饰函数以后的操做"""
return ret
return inner

装饰器功能:在不改变原函数的基础上,为原函数增长一些额外的功能,log,登陆注册等

 

#函数的有用信息

def login(username, password):
    """
    此函数须要用户名,密码两个参数,完成的是登陆的功能。
    :return: True 登陆成功。 False登陆失败。
    """
    # print(login.__name__)
    # print(login.__doc__)
    print('登陆成功...')
    return True

print(login.__name__)
print(login.__doc__)

#输出:login

    此函数须要用户名,密码两个参数,完成的是登陆的功能。
    :return: True 登陆成功。 False登陆失败。

  

def wrapper(f):
    def inner(*args, **kwargs):
        print(f.__name__)
        print(f.__doc__)
        """执行函数以前的操做"""
        ret = f(*args, **kwargs)
        """执行函数以后的操做"""
        return ret
    return inner

@wrapper
def login(username, password):
    """
    此函数须要用户名,密码两个参数,完成的是登陆的功能。
    :return: True 登陆成功。 False登陆失败。
    """
    print('登陆成功...')
    return True
login(1, 2)

  引入一个模块

from functools import wraps

def wrapper(f):
    @wraps(f)
    def inner(*args, **kwargs):
        """执行函数以前的操做"""
        ret = f(*args, **kwargs)
        """执行函数以后的操做"""
        return ret
    return inner

@wrapper
def login(username, password):
    """
    此函数须要用户名,密码两个参数,完成的是登陆的功能。
    :return: True 登陆成功。 False登陆失败。
    """
    a = 2
    c = 4
    print('登陆成功...')
    return True

print(login.__name__)
print(login.__doc__)

带参数的装饰器

 

import time


def timer_out(flag1):  #falg1 = flag
    def timer(f):
        def inner(*args, **kwargs):
            if flag1:
                start_time = time.time()
                time.sleep(0.3)
                ret = f(*args, **kwargs)
                end_time = time.time()
                print('执行效率%s' % (end_time-start_time))
                return ret
            else:
                ret = f(*args, **kwargs)
                return ret
        return inner
    return timer

flag = True        #若是不想装饰,把TURE改为False

@timer_out(flag)  # 1,步 timer_out(flag) == timer 2,@与timer结合,变成你熟悉的装饰器 @timer
def func1():
    print(111)


@timer_out(flag)
def func2():
    print(222)


@timer_out(flag)
def func3():
    print(333)

func1()
func2()
func3()

#

111
执行效率0.3004300594329834
222
执行效率0.30065345764160156
333
执行效率0.3003878593444824

 

 局部只能引用全局的变量,不能修改,若是要修改,global。

count = 1

def func4():
    count = count + 1
    print(count)

func4()


#报错,coun在局部没有定义
# 子函数只能引用父函数的变量,不能修改,若是要修改,nonlocal。
def func4():

    count = 3
    def inner():
        nonlocal count
        count = count + 1
        print(count)
func4()

多个装饰器装饰一个函数

def wrapper1(func): # func = f函数名
    def inner1():
        print('wrapper1 ,before func')  # 2
        func()
        print('wrapper1 ,after func')  # 4
    return inner1


def wrapper2(func):  # func = inner1
    def inner2():
        print('wrapper2 ,before func')  # 1
        func()  # inner1()
        print('wrapper2 ,after func')  # 5
    return inner2

@wrapper2  # f = wrapper2(f) 里面的f新变量 = inner1 外面的f最新变量 = inner2
@wrapper1  # f = wrapper1(f) 里面的f函数名  外面的f新变量=inner1
def f():
    print('in f')  # 3

f()  # inner2()
'''
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
'''

开放封闭原则:

 

1.对扩展是开放的

 

    为何要对扩展开放呢?

 

    咱们说,任何一个程序,不可能在设计之初就已经想好了全部的功能而且将来不作任何更新和修改。因此咱们必须容许代码扩展、添加新功能。

 

  2.对修改是封闭的

 

    为何要对修改封闭呢?

 

    就像咱们刚刚提到的,由于咱们写的一个函数,颇有可能已经交付给其余人使用了,若是这个时候咱们对其进行了修改,颇有可能影响其余已经在使用该函数的用户。

 

装饰器完美的遵循了这个开放封闭原则。

相关文章
相关标签/搜索