函数的闭包和装饰器

函数的闭包

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

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

例如:一个简单的例子

def outter():
    x = 11
    def inner():
        print(x)
    return inner
res = outter()  #把inner的内存地址赋值给res了
def func():
    x =333
    res()    #等价于inner()
func()    #111

在给函数体传值的时候有两种方式:

1.传参

def outter(name):
    print(name)

2.闭包

def outter(x,y):
    def inner():
       if x > y:
            return x
          return y
      return inner

res = outter(1,4)
res()

介绍了一个模块:

import requests

第一个直接给函数传值

url1 = 'https://www.baiducom'
def my_get(url1)
    response =requests.get(url1)
    if response.status_code == 200:
        print(len(response.text)
my_get(url1)

第二个是闭包的形式传参

def outter(url):
    def inner():
        response  = requests.get(url)
        if response.status_code == 200:
            print(len(response.text))
    return inner

res = outter('https://www.baidu.com')

装饰器(*******)

  我们可以把器当成一个工具,装饰就是给对象添加一些别的功能

为什么要使用装饰器:

  开放封闭的原则:

    开放:对扩展开放

    封闭:对修改封闭

  装饰器要遵循两个原则:

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

    2.不改变被装饰的对象

这只是一个简易的装饰器

升级版的装饰器

import time
def index():
    time.sleep(3)
    print('你好')
    return 'index'

def login():
    time.sleep(1)
    print('您好')
    return 'login'
 
def outter(func):
    def inner(*args,**kwargs)
    start = time.time()
    res = func(*args,**kwargs)
    return res
    end = time.time()
    print('时间是%s'%(end-start)
    return inner
index = outter(index)
login = outter(login)
index()
login()    

装饰器语法糖

import time

def outter(func):  # func = 最原始的index函数的内存地址
    def get_time(*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)  # outter(最原始的login函数的内存地址)
# index = outter(index)
# home = outter(home)

@outter  # index = outter(index)  outter(最原始的index的函数的内存地址)
def index():
    time.sleep(3)
    print('你好')
    return 'index'
# res1 = index()


@outter  # login = outter(login)
def login(name):
    time.sleep(1)
    print('%s is sb'%name)
    return 'login'
# res = login('egon')

@outter  # home = outter(home)
def home(*args,**kwargs):
    time.sleep(1)
    return 'home'


# login = outter(login)  # outter(最原始的login函数的内存地址)
# index = outter(index)
# home = outter(home)


index()
login('yzy')
home()

语法糖的书写要求:

1.语法糖在书写的时候应该与被装饰对象紧紧挨着

2.两者之间不能有空格

 

对我们来说有一个比较简便的装饰器模板

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

多层装饰器:

import time


user_dic = {'is_login':None}


def outter(func):  # func = 最原始的login函数的内存地址
    def get_time(*args, **kwargs):  # args = ('egon',) 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

def login_auth2(data_source,x,t):
    # data_source = 'file'
    def login_auth(func):
        # func = index
        def inner(*args,**kwargs):  # 这里的参数是跟被装饰函数的参数一一对应
            if user_dic['is_login']:
                res = func(*args, **kwargs)
                return res
            else:
                if data_source == 'file':
                    username = input('please input your username>>>:').strip()
                    password = input('please input your password>>>:').strip()
                    if username == 'jason' and password == '123':
                        user_dic['is_login'] = True
                        res = func(*args,**kwargs)
                        return res
                    else:
                        print('username or password error')
                elif data_source == 'MySQL':
                    print('from MySQL')
                elif data_source == 'ldap':
                    print('ldap')
                else:
                    print('暂无该数据来源')
        return inner
    return login_auth

# 装饰器在装饰的时候  顺序从下往上
# 装饰器在执行的时候  顺序从上往下
# res = login_auth2('MySQL')
@login_auth2('file',1,2) # index = login_auth(get_time)  index = inner函数的内存地址
# @login_auth
@outter  # get_time = outter(index)  index是最原始的index
def index():
    time.sleep(1)
    print('index')
    return 'index'
index()
View Code

装饰器的修复技术

import time


user_dic = {'is_login':None}


def outter(func):  # func = 最原始的login函数的内存地址
    def get_time(*args, **kwargs):  # args = ('egon',) 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

def login_auth2(data_source,x,t):
    # data_source = 'file'
    def login_auth(func):
        # func = index
        def inner(*args,**kwargs):  # 这里的参数是跟被装饰函数的参数一一对应
            if user_dic['is_login']:
                res = func(*args, **kwargs)
                return res
            else:
                if data_source == 'file':
                    username = input('please input your username>>>:').strip()
                    password = input('please input your password>>>:').strip()
                    if username == 'jason' and password == '123':
                        user_dic['is_login'] = True
                        res = func(*args,**kwargs)
                        return res
                    else:
                        print('username or password error')
                elif data_source == 'MySQL':
                    print('from MySQL')
                elif data_source == 'ldap':
                    print('ldap')
                else:
                    print('暂无该数据来源')
        return inner
    return login_auth

# 装饰器在装饰的时候  顺序从下往上
# 装饰器在执行的时候  顺序从上往下
# res = login_auth2('MySQL')
@login_auth2('file',1,2) # index = login_auth(get_time)  index = inner函数的内存地址
# @login_auth
@outter  # get_time = outter(index)  index是最原始的index
def index():
    time.sleep(1)
    print('index')
    return 'index'
index()
View Code

 

posted @ 2019-07-11 17:26  Yzy~Yolo  阅读(145)  评论(0编辑  收藏  举报