闭包函数、装饰器

闭包函数
1.闭:定义在函数内部的函数
2.包:内部函数引用了外部函数作用域的名字

 闭包函数:只需要传一次参,下面无论在哪用到,直接拿那个名字就可以了

特点:只给内部传参,需要什么传什么,永远不会变

def outter():  #先定义一个outter函数
    x = 111
    def inner():
        print(x)
    return inner
res = outter()  # res就是inner函数内存地址

def func():
    x = 333
    res()
func()

给函数体传值的第一种方式 :传参,直接传递数据

def index1(username):
    print(username)

给函数体传参的第二种方式 闭包(包起来,我给你)

def outter(x,y):
    # 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())
print(res1())
print(res1())
res2 = outter(90,200)
print(res2())
print(res2())
print(res2())
print(res2())
print(res2())
print(res2())
View Code

需要注意的是

def outter (x,y)
与
def outter():
x = 1
y = 10
这两种本质是一样的,都是在outter里面绑定两个名字,产生两个值

import requests

第一个直接给函数传参

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

my_get(url1)
my_get(url1)
my_get(url1)
my_get('https://www.baidu.com')
my_get('https://www.baidu.com')
my_get('https://www.baidu.com')

第二种给函数传参的方式 闭包

def outter(url):
# 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_jd()
my_baidu = outter('https://www.baidu.com')
my_baidu()
my_baidu()
my_baidu()
my_baidu()
my_baidu()


装饰器:
器:就是一个工具
装饰:给被装饰对象添加新的功能

为什么要用装饰器
开放封闭原则:
开放:对扩展开放
封闭:对修改封闭

装饰器(可调用对象)必须遵循的两个原则:
1.不改变被装饰对象源代码
2.不改变被装饰对象(可调用对象)调用方式
def index():
pass
index()

如何用
"""
import time  #统计时间
print(time.time())
#1562812014.731474 时间戳 当前时间距离1970-1-1 00:00:00相差的秒数
#1970-1-1 00:00:00是Unix诞生元年


time.sleep(3) # 让cpu谁三秒 让你的程序暂停三秒
print('FBI warning!')

 

 简单版本装饰器

1.统计index函数执行的时间

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

start = time.time()
index()
end = time.time() #cpu运行代码的时候速度是非常快的,代码与代码之间距离的时间特别的短,
print('index run time:%s'%(end-start))

1.统计index函数执行的时间

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

def outter(func):   #func = index函数的内存地址
    # func = index
    def get_time(func):   #func=index函数
        start = time.time()
        func()   #func=index函数内存地址()  直接调用   运行结束时间
        end = time.time()  #运行结束时间
        print('index run time:%s'%(end-start))
    return get_time
# res = outter(index)   #res变量名   想等于什么就是什么
# res()
index = outter(index)  #函数名只要加括号,优先级最高  outter(最开始的index函数内存地址)
#index指向get_time函数的内存地址
index()

升级版装饰器

 

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

def login(name):   #形参是位置形参
    time.sleep(1)
    print('%s is sb'%name)

def outter(func):
    # func = index
    def get_time(*args,**kwargs):   #func = login函数的内存地址
        start = time.time()
        func(*args,**kwargs)   #args = ('egon',)  kwargs={}
        end = time.time()
        print('index run time:%s'%(end-start))
    return get_time
# res = outter(index)
# res()
login = outter(login)    #outter(最原始的login函数的内存地址)   login是get_time
login('egon')
index = outter(index)   #最原始的index函数
index()
View Code

函数参数的问题
无参函数和有参函数都可以直接调用???
函数可以接收任意数量的参数

装饰器的模板

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

 

装饰器语法糖

@outter  #本质是在最前面

@的工作原理:固定语法会将紧挨着它下面的可调用的名字当做它的参数自动传入,直接执行

例如:

index = outter(index)

(自动outter())

 

mport 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('澳门最大线上赌场开业啦 性感tank在线发牌!')
    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('egon')
home()
View Code

注:语法糖在书写的时候应该与被装饰对象紧紧挨着
两者之间不要有空格

 

posted @ 2019-07-14 02:51  Aomur  阅读(169)  评论(0编辑  收藏  举报