闭包,装饰器

一、闭包函数

 1、简介

#闭:指的是闭包函数是定义在一个函数内部的函数
#包:该内部函数包含外层函数作用域名字的引用(内外函数中间部分)

  需要结合函数对象的概念(return内部函数名),将闭包函数返回到全局作用域去使用,从而打破函数的层级限制

#特点:1.定义在另一个函数内的函数
    2.内部的的函数访问了外部的名称(数据)    注意:不包含全局的

二、为何用闭包函数   

#闭包函数提供了一种为函数体传值的解决方案

如何用闭包函数

    def outter():
        x=111
        def inner():
            print(x)
        return inner

    f=outter() #f=outter内的inner
    f()
#定义闭包函数,内层函数看成是定义一个变量,函数名是变量名
def outer():
    a=10
    return a
f=outer()
print(f)

def outer():
    def inner():        #类似a=10
        pass
    return inner         #类似return a
f=outer()                 执行外层函数,拿到的是内层函数的内存地址
print(f)
f()
加深对创建闭包函数的理解

为函数传值的两种方式

def func(x,y):
     print(x+y)

func(1,2)
为函数体传值的方式一:参数
 def outter(x,y):
     # x=1
     # y=2
     def func():
         print(x+y)
     return func

 f=outter(1,2)
 f()
为函数体传值的方式二:闭包
#直接通过参数传参
def get(url):
    response=requests.get(url)
    if response.status_code == 200:
        print(len(response.text))
get('https://www.baidu.com')    #来一次就需要输入完整的路径,较麻烦
get('https://www.baidu.com')
get('https://www.baidu.com')
get('https://www.tmall.com')

#即使指定,这是全局作用域,任何函数都能访问到都能访问到,
    url1='https://www.baidu.com'
    url2='https://www.tmall.com'
    get(url1)
    get(url1)

    get(url2)
    get(url2)
------------------------------------------------------------------------

#通过闭包函数传参
def bar(url):
    def get():
        response=requests.get(url)
        if response.status_code == 200:
            print(len(response.text))
    return get
baidu=bar('https://www.baidu.com')    #指定好一个,下次直接使用,是绑定的关系
baidu()
baidu()
baidu()
tmall=bar('https://www.tmall.com')     #将该地址绑定给tmall
tmall()
例子

二、闭包函数之装饰器

1、简介

#装饰器就是用一个函数去扩展另一个已存在的函数的功能
#饰器其实是闭包函数的一种应用方式

#装饰器的原则:
  1、不修改装饰对象的源代码
  2、不修改被装饰对象的源代码
#装饰器的目标:
  在遵循1和2的条件下,为被装饰对象添加新功能

2、使用

无参装饰器

import time
def index():
    print('from index')
    time.sleep(3)

def wrapper(func):
    def inner():
        start=time.time()
        func()
        stop = time.time()
        print('run time %s' %(stop-start))
    return inner


#闭包函数,f=inner的内存地址
f = wrapper(index)     #index = wrapper(index)   变量名可随意命名
f()                             #index()
最简单的无参装饰器

 有参装饰器

def auth(data_param):
    def func_outer(func_param):
        def func_inner(*args,**kwargs):
            if data_param == 'login':
                print('login interface-------')
                name = input("user: ")
                pwd = input("pwd: ")
                if name == 'pdun' and pwd == '123':
                    print('login successful')
                    res=func_param(*args,**kwargs)
                    return res

            elif data_param == 'register':
                print('register interface--------- ')
                name = input("user: ")
                pwd = input("pwd: ")
                print('register successful ')
        return func_inner
    return func_outer


#来到这一行,看见函数加括号,就不考虑@,先执行函数,也就是拿到return值,func_outer
#相当于这一行变为@func_outer,此时函数没有括号,此时就会把正下方的函数当作参数,传给func_outer,就是func_outer(func)
#并且会把return返回给正下方的函数,func=func_inner

@auth('register')
def func(name):
    print('hello
%s'%name)
    return

func('pdun')

@auth('login')
def func(name):
    print('hello
%s'%name)

func('Moker')

-----------------------------
register interface--------- 
user: qq
pwd: qq
register successful 
login interface-------
user: pdun
pwd: 123
login successful
hello
Moker
View Code

 语法糖

import time
def outer(x):
    def inner(*args,**kwargs):
        s=time.time()
        res=x(*args,**kwargs)
        o=time.time()
        return res
    return inner

@outer
def func(name):
    time.sleep(1)
    print('my name is %s' %(name))
    return 0

func('pdun')
语法糖
import functools
def wapper(func):
    # @functools.wraps(func)       保留函数的元信息
    def inner(*args,**kwargs):
        return func(*args,**kwargs)

    return inner

@wapper
def f1():
    pass

print(f1.__name__)


----------------------------
inner
解开注释后
f1
functools工具
原文地址:https://www.cnblogs.com/pdun/p/10269289.html