9.23 闭包和装饰器

Posted lidandanaa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9.23 闭包和装饰器相关的知识,希望对你有一定的参考价值。

1.闭包函数:把闭包函数内部的变量和函数包起来,返回闭包函数内部的函数。闭包函数也是一个函数。

def f1():
    def f2():
        print('from f2')
    return f2
res=f1()
res()   #from f2
def f1(url):
    def f2():
        print(url)
    return f2
res=f1('www.taobao.com')
res()  #www.taobao.com

两种为函数传参的方式:

a.使用参数的形式

def f1(x):
    print(x)
f1(1) #1

b.包给函数

def outter(x):
    x=1
    def inner():
        print(x)
    return inner
f=outter(1)
f() #1

2.装饰器:为被装饰器对象添加额外功能,定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外功能。

装饰器的实现必须遵守的两大原则:

a.不修改被装饰对象的源代码

b.不修改被装饰对象的调用方式

3.装饰器的使用

改变源代码

import time

def index():
    '''被装饰的函数'''
    start=time.time()
    print('welcome to index')
    time.sleep(1)
    end=time.time()
    print(f'运行时间是:end-start')
index()
运行结果:
welcome to index
运行时间是:1.0000569820404053

编写重复代码:

import time
def index():
    print('index')
    time.sleep(1)

def f1():
    print('f1')
    time.sleep(1)

start=time.time()
index()
end=time.time()
print(end-start)

start=time.time()
f1()
end=time.time()
print(end-start)
运行结果:
index
1.0000574588775635
f1
1.0000569820404053

第一种传参方式:改变调用方式

import time
def index():
    print('index')
    time.sleep(1)

def time_count(func):
    start = time.time()
    func()
    end=time.time()
    print(end-start)
time_count(index) 
运行结果:
index
1.0000572204589844

第二种传参方式:包给函数-外包

import time
def index():
    print('index')
    time.sleep(1)

def time_count(func):   #func是真正的index
    def wrapper():
        start = time.time()
        func()
        end=time.time()
        print(end-start)
    return wrapper

res=time_count(index)  #res==wrapper
res()
运行结果:
index
1.0010573863983154

4.完善装饰器:

wrapper 的返回值和index的返回值相同

import time
def index():
    print('index')
    time.sleep(1)
    return 123

def time_count(func):   #func是真正的index
    def wrapper():
        start = time.time()
        func()
        end=time.time()
        print(end-start)
        return res    
    return wrapper

f1=time_count(index)  #res==wrapper
res=f1()
print(res)
运行结果:
index
1.0010573863983154
123

给index传参的实现:

import time
def index():
    print('index')
    time.sleep(1)

def home(name):
    print(f'welcome name to home page')
    time.sleep(1)
    return name

def time_count(func):   #func是真正的index
    def wrapper(*args,**kwargs):
        start = time.time()
        res=func(*args,**kwargs)
        end=time.time()
        print(end-start)
        return res
    return wrapper

res=time_count(home) #res==wrapper
f1=res('nick')
print(f1)
运行结果:
welcome nick to home page
1.0000569820404053
nick

5.装饰器语法糖:在被装饰函数正上方,并且是单独的一行@装饰器

def time_count(func):   #func是真正的index
    def wrapper(*args,**kwargs):
        start = time.time()
        res=func(*args,**kwargs)
        end=time.time()
        print(end-start)
        return res
    return wrapper

@time_count
def index():
    print('index')
    time.sleep(1)
    return 123

@time_count
def home(name):
    print(f'welcome name to home page')
    time.sleep(1)
    return name

# res=time_count(home) #res==wrapper
f1=home('nick')
print(f1)

f2=index()
print(f2)
运行结果:
welcome nick to home page
1.0000572204589844
nick
index
1.0000572204589844
123

6.装饰器模板:

def deco(func):
    def wrapper(*args,**kwargs):
        res=func(*args,**kwargs)
        return res
    return wrapper

7.三层的有参装饰器:

usename_list=[]

def sanceng(role):
    def login_deco(func):
        def wrapper(*args,**kwargs):
            usename_inp=input('请输入用户名:')
            pwd_inp=input('请输入密码:')

            if usename_list:
                print('已经登录,无须重复')
                res=func(*args,**kwargs)
                return res
            with open(f'role_info.txt','r',encoding='utf8') as fr:
                for role_info in fr:
                    usename,pwd=role_info.strip().split(':')
                    if usename==usename_inp and pwd==pwd_inp:
                        print('登录成功')
                        usename_list.append(usename)
                        res = func(*args, **kwargs)
                        return res
                else:
                    print('登录失败')
        return wrapper
    return login_deco

@sanceng('admin')
def index (x,y):
    print('index')
    print('x,y',x,y)

    return 123

res=index(10,30)
运行结果:
请输入用户名:ldd
请输入密码:123
登录成功
index
x,y 10 30

以上是关于9.23 闭包和装饰器的主要内容,如果未能解决你的问题,请参考以下文章

Python闭包和装饰器

Python闭包和装饰器

python-闭包和装饰器-02-装饰器(decorator)

python-闭包和装饰器-02-装饰器(decorator)

闭包和装饰器

装饰器和闭包