闭包函数及装饰器

闭包函数

闭包函数的定义:

  闭:定义在函数内部的函数

  包:内部函数引用了外部函数作用域的名字

给函数体传值的两种方式:

1.传参

 

def index1(username):
    print(username)

 

2.闭包

def outter(x,y):  #在函数内传参,在res1中调用,相当于x=1,y=40
    # x = 1
    # y = 40
    def my_max():
        if x > y:
            return x
        return y
    return my_max
res1 = outter(1,40)  # res就是my_max函数的内存地址
print(res1())   #这里打印的还是1和40,想结束不让他打印1和40的话只能结束程序或者再传其他参数
print(res1())
print(res1())
res2 = outter(90,200)
print(res2())
print(res2())
import requests  

def outter(url):  #给函数传参,在my_jd中定义实参传给形参
    # url = 'https://www.jd.com'  #固定传参
    def my_get():
        response = requests.get(url)
        if response.status_code == 200:  
            print(len(response.text))
    return my_get
my_jd = outter('https://www.jd.com')  #my_jd接收的是my_get的内存地址
my_jd()
my_jd()
my_baidu = outter('https://www.baidu.com')
my_baidu()
my_baidu()
my_baidu()
my_baidu()
my_baidu()

 

 

装饰器

装饰器:

  器:就是一个工具

  装饰:给被装饰对象添加新的功能

为什么要用装饰器?

  开放封闭原则:

    开放:对扩展开放

    封闭:对修改开放

  装饰器(可调用对象)必须遵循的两个原则:

    1.不改变被装饰对象的源代码

    2.不改变被装饰对象(可调用对象)调用方式

 

首先写一个time模块的示例

import time
def index():
    time.sleep(3)   # 让CPU睡3秒
    print('开业啦')

start = time.time()  # 程序运行开始时的时间
index()
end = time.time()    #程序结束时的时间
print('index run time:%s'%(end-start))  # 计算程序从开始到结束所用的时间

 

如何写一个计算时间的装饰器呢?不同的函数名都可以应用

import time
def index():
    time.sleep(3)
    print('开业啦')

def outter(func):  # func = 最原始的index函数的内存地址
    def get_time():
        start = time.time()
        func()  # func = index函数的内存地址() 直接调用
        end = time.time()
        print('index run time:%s'%(end-start))
    return get_time
index = outter(index)  # outter(最原始的index函数内存地址)
# index指向get_time函数的内存地址
index()

如何写一个同时支持有参和无参的装饰器

import time
def index():   #无参函数
    time.sleep(3)
    print('开业啦')
    return 'index'
res1 = index()

def login(name): #有参函数
    time.sleep(1)
    print('%s is s'%name)
    return 'login'
res = login('zhangsan')

def outter(func):  # func = 最原始的login函数的内存地址
    def get_time(*args, **kwargs):  # 写*args和**kwargs可以同时支持有参和无参,可以接收任意数量的参数
        start = time.time()
        res = func(*args, **kwargs)  # 最原始的login函数的内存地址() 直接调用  func('egon')
        end = time.time()
        print('func run time:%s'%(end-start))
        return res
    return get_time
login = outter(login)

语法糖

def outter(func):  # func = 最原始的index函数的内存地址
    def get_time(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)  # 最原始的index函数的内存地址() 直接调用  
        end = time.time()
        print('func run time:%s'%(end-start))
        return res
    return get_time


@outter   # 语法糖,等同于index = outter(index),outter会直接把离他最近的一个函数名当做自己的参数传入
def index():
    time.sleep(3)
    print('开业啦')
    return 'index'

 

装饰器模板

def outter(func):
    def inner(*args, **kwargs)
        print('执行被装饰函数之前,可以做的操作')
        res = func(*args, **kwargs)
        print('执行被装饰函数之后,可以做的操作')
        return res
    return inner

认证装饰器

  执行函数index之前必须先输入用户名和密码 正确之后才能执行index,否则提示用户输入错误 结束程序。

import time
user_dic = {'is_login':None}  #定义一个字典存放用户登录的状态

def login_auth(func):
    # func = index
    def inner(*args,**kwargs):
        if user_dic['is_login']:  # 如果用户已经在登录状态
            res = func(*args, **kwargs)  
            return res  #直接将参数返回
        else:
            username = input('please input your username>>>:').strip()
            password = input('please input your password>>>:').strip()
            if username == 'wu' and password == '123':
                user_dic['is_login'] = True
                res = func(*args,**kwargs)
                return res
            else:
                print('username or password error')
    return inner

装饰器补充 @wraps

def outter(func):
    @wraps(func)    
    def inner(*args, **kwargs)
        print('执行被装饰函数之前,可以做的操作')
        res = func(*args, **kwargs)
        print('执行被装饰函数之后,可以做的操作')
        return res
    return inner

# 用户查看被装饰函数的函数名的时候查看到的就是被装饰函数本身
# 用户查看被装饰函数的注释的时候查看到的就是被装饰函数的注释

 

posted @ 2019-07-11 22:35  Key丶橙子哥  阅读(179)  评论(0编辑  收藏  举报