Python学习-Day14

1.闭包函数

# 闭包函数 = 函数嵌套定义+函数对象+名称空间与作用域

# 闭包函数

# 1.闭:指的是该函数是定义在一个函数内部的函数

# 2.包:指的是该函数访问了一个来自于外层函数的变量

# 为函数体传参:

# 方案一:直接使用参数的形式传递

# def wrapper(x):

#    print(x)

#

# wrapper(111)

# wrapper(222)

# 方案二:把函数体想要的参数包给它

def outter(x):

# x = 111

    def wrapper():# wrapper = 闭包函数的内存地址

        print(x)

return wrapper# 一定不要加括号

    # return 闭包函数的内存地址

f1 = outter(111)# f = 闭包函数的内存地址

f2 = outter(222)# f = 闭包函数的内存地址

2.无参装饰器

'''

1.什么是装饰器

器:工具

    装饰:为被装饰者添加额外功能2.为何要有装饰器

    软件一旦上线之后,就应该遵循开放封闭原则:        1.开放指的是对拓展新功能开放        2.封闭指的是对修改源代码封闭

定义装饰器的目的:

            定义装饰器函数就是为了在遵循1和2的前提下为其他函数添加新功能        ps。不修改被装饰对象指的是定义与调用都不能修改3.如何用装饰器'''

# 被装饰对象index如下:

import time

def index(x,y):

time.sleep(1)

print('index===>',x,y)

index(1,2)

# 二、为index添加新功能

# 2.1 方案一:直接修改源代码为被装饰对象index添加新功能

# 问题:修改了源代码

#

# import time

#

# def index(x,y):

#    start_time = time.time()

#    time.sleep(1)

#    print('index===>',x,y)

#    stop_time = time.time()

#    print('run time is: %s' %(stop_time - start_time))

#

# index(1,2)

# 2.2 方案二:找到所有调用index的位置,然添加代码

# 问题:需要写好多段重复代码

# import time

#

# def index(x,y):

#    time.sleep(1)

#    print('index===>',x,y)

#

#

# start_time = time.time()

# index(1,2)

# stop_time = time.time()

# print('run time is: %s' %(stop_time - start_time))

# 2.3 方案三:把装饰功能写到一个函数内

# 问题:装饰功能被写死了,只能用来装饰index函数了

# import time

#

# def index(x,y):

#    time.sleep(1)

#    print('index===>',x,y)

#

# def wrapper():

#    start_time = time.time()

#    index(1,2)

#    stop_time = time.time()

#    print('run time is: %s' %(stop_time - start_time))

#

# wrapper()

# 2.4 方案四:把wrapper函数内的index修改为参数的形式

# 问题:直接为wrapper函数传参的方案不行,因为原函数的调用

#      是在全局调用index(1,2), 而现在的调用统一都变成了wrapper(index),这修改了被装饰函数的调用方式

# import time

#

# def index(x,y):

#    time.sleep(1)

#    print('index===>',x,y)

#

#

# def wrapper(func):

#    start_time = time.time()

#    func(1,2)

#    stop_time = time.time()

#    print('run time is: %s' %(stop_time - start_time))

#

# wrapper(index)

# 2.5 方案五:基于闭包函数把wrapper函数想要的参数包给它,然后基于函数对象把闭包函数wrapper返回到全局,赋值给原函数名

# 问题:把index伪装成了wrapper,但伪装的不够像:参数的传递与原函数不一致

# import time

#

# def index(x,y):

#    time.sleep(1)

#    print('index===>',x,y)

#

# def outter(func):

#    def wrapper(x,y):

#        start_time = time.time()

#        func(x,y)

#        stop_time = time.time()

#        print('run time is: %s' %(stop_time - start_time))

#    return wrapper

# index = outter(index)

# index(1,2)

# 2.6 方案六:在方案五的基础上基于*args,**kwargs把wrapper的参数伪装成跟被装饰函数一模一样

# 问题:返回值与原函数不一致

#

# import time

#

# def index(x,y):

#    time.sleep(1)

#    print('index===>',x,y)

#

# def home(name):

#    time.sleep(0.5)

#    print('welcome %s to home page' %name)

#    return 123

#

# def outter(func):

#    # func = index

#    def wrapper(*args,**kwargs):

#        start_time = time.time()

#        func(*args,**kwargs)

#        stop_time = time.time()

#        print('run time is: %s' %(stop_time - start_time))

#    return wrapper

#

# index=outter(index)

# home=outter(home)

#

# # index(1,2)

# res=home('egon')

# print(res)

# 2.7 方案七:在方案六的基础上把wrapper函数的返回值与被装饰函数保持一致

# 问题:装饰器的使用不够简洁

# import time

# from functools import wraps

#

# def timmer(func):

#    # func = index

#    @wraps(func)

#    def wrapper(*args,**kwargs):

#        start_time = time.time()

#        res=func(*args,**kwargs)

#        stop_time = time.time()

#        print('run time is: %s' %(stop_time - start_time))

#        return res

#    return wrapper

#

# def index(x,y):

#    time.sleep(1)

#    print('index===>',x,y)

#

# def home(name):

#    "home的文档注释"

#    time.sleep(0.5)

#    print('welcome %s to home page' %name)

#    return 123

#

#

# index=timmer(index)

# home=timmer(home)

#

# # res=index(1,2)

# # print(res)

#

# # res=home('egon')

# # print(res)

#

#

# # print(home.__name__)

# # print(home.__doc__)

# help(home)

# 2.8 方案八:在方案7的基础上使用装饰器的语法糖@符号让装饰器的使用变得简洁

import time

from functoolsimport wraps

def timmer(func):

# func = index

# @wraps(func)

    def wrapper(*args,**kwargs):

start_time = time.time()

res=func(*args,**kwargs)

stop_time = time.time()

print('run time is: %s' %(stop_time - start_time))

return res

return wrapper

@timmer  # index=timmer(index)

def index(x,y):

time.sleep(1)

print('index===>',x,y)

@timmer  # home=timmer(home)

def home(name):

"""home的文档注释"""

    time.sleep(0.5)

print('welcome %s to home page' %name)

return 123

index(1,2)

home('egon')

3.叠加多个装饰器

# 1、无参装饰器的模板

# def outter(func):

#    def wrapper(*args,**kwargs):

#        res=func(*args,**kwargs)

#        return res

#    return wrapper

#2、叠加多个装饰器

#2.1 加载顺序:自下而上

#2.2 执行顺序:自上而下运行内层的wrapper函数

# def deco1(func1):  # func1 = wrapper2的内存地址

#    def wrapper1(*args,**kwargs):

#        print('wrapper1====>')

#        res1=func1(*args,**kwargs)

#        return res1

#    return wrapper1

#

# def deco2(func2):  # func2 = wrapper3的内存地址

#    def wrapper2(*args,**kwargs):

#        print('wrapper2====>')

#        res2=func2(*args,**kwargs)

#        return res2

#    return wrapper2

#

# def deco3(func3):  # func3 = 最原始的那个被装饰函数的内存地址

#    def wrapper3(*args,**kwargs):

#        print('wrapper3====>')

#        res3=func3(*args,**kwargs)

#        return res3

#    return wrapper3

#

#        # index=wrapper1的内存地址

# @deco1  # deco1(wrapper2的内存地址)=>wrapper1的内存地址

# @deco2  # deco2(wrapper3的内存地址)=>wrapper2的内存地址

# @deco3  # deco3(最原始的那个被装饰函数的内存地址)=>wrapper3的内存地址

# def index(x,y):

#    print('index=>',x,y)

#

# index(1,2)

#

# """

# wrapper1====>'

# wrapper2====>

# wrapper3====>

# index=>1,2

# """

#3 案例

import time

def deco1(func1):

def wrapper1(*args,**kwargs):

start_time = time.time()

res1=func1(*args,**kwargs)

stop_time = time.time()

print(stop_time - start_time)

return res1

return wrapper1

def deco2(func2):

def wrapper2(*args,**kwargs):

inp_name =input('username>>>: ').strip()

inp_pwd =input('password>>>: ').strip()

if inp_name =="egon" and inp_pwd =="123":

print('login successful')

res2=func2(*args,**kwargs)

return res2

else:

print('username or password error')

return wrapper2

@deco2

@deco1

def index(x,y):

time.sleep(1)

print('index=>',x,y)

index(1,2)

4.有参装饰器


def outter(engine ='file'):

def deco2(func2):

def wrapper2(*args,**kwargs):

inp_name =input('username>>>: ').strip()

inp_pwd =input('password>>>: ').strip()

if engine =="file":

print('基于file的认证')

if inp_name =="egon" and inp_pwd =="123":

print('login successful')

res2=func2(*args,**kwargs)

return res2

else:

print('username or password error')

elif engine =='mysql':

print('基于mysql的认证')

elif engine =='ldap':

print('基于ldap的认证')

else:

print('未知的engine')

return wrapper2

return deco2

@outter(engine='mysql')# @deco2 # index=deco2(index)

def index(x,y):

print('index=>',x,y)

index(1,2)# index=>wrapper

# 有参装饰器的模板:

# def outter2(x,y,z,a,b):

#    def outter1(func):

#        def wrapper(*args,**kwargs):

#            res=func(*args,**kwargs)

#            return res

#        return wrapper

#    return outter1

你可能感兴趣的:(Python学习-Day14)