函数作为返回值、闭包函数、装饰器day11

今日学习总结:

一、函数作为返回值

ps:print 仅仅是打印在控制台,return是将return后面的部分作为返回值,作为函数的输出。可以用变量接走继续使用该返回值做其他事情。

    返回函数

def test3():
    print("hello")    
    return test3                   #test3是个地址,返回给函数test3()  .注意test3() 也是一个地址,因为test3是个地址给了test3()
z=test3()                                   
z()                                #调用函数
def test3():
    print("in the test3")
    return 'test3'                #表示返回一个字符串值“test3”返回给函数 test3()
z=test3()                         #把字符串值'rest3' 赋给变量z
print(z)                          #这时就不需要在()了,要想有结果必须要打印
def test2():
    print("in the test2")#指定返回
    return 55
def test4():
    print("in the test4")#返回函数
    return test2()       #表示把test2()返回给test4()
a=test4()                #表示执行test4()函数,把test2()给a
print(a)


结果:
in the test4
in the test2
55

二、闭包函数(重要)

“闭包”,就是在构造函数体内定义另外的函数作为目标对象的方法函数,而这个对象的方法函数反过来引用外层函数体中的临时变量
1.封闭、包裹。闭包函数必须在函数内部定义
2.作用:闭包函数可以引用外层函数的名字
3.闭包函数是函数嵌套、函数对象、名称空间与作用域的结合,必须返回函数
4.函数内部可以直接读取全局变量,在函数外部自然无法读取函数内的局部变量。
那怎么样才能 从外部读取到内部变量?

如何从外部读取局部变量?

出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。

答;那就是在函数的内部,再定义一个函数。


例子:无参数闭包函数
def outer():
    number = 100
    def inner():                 #在这里inner是闭包
        print(number)
    return inner                #将inner地址返回给函数outer()
func = outer()                  #将outer() 它表示地址赋值给func
func()                            #调用函数


def outer():
    number = 100
    def inner():                  #在这里inner是闭包
        print(number)
    return inner                  #将inner地址返回给函数outer()
outer()()                         #将outer()是地址  后面加()表示调用outer()函数

例子:有参数闭包函数

def outer(number):
    def inner():
        print(number)
    return inner
func = outer(12)  # 表示调用函数outer 返回inter的地址 .然后赋值给变量func
func()            # 表示调用函数

例子:用有参数闭包函数 爬取某个网站,打印获取数据的长度

import requests                                #导入发送请求包
def spider_outer(url):
    def spider_inner():
        response = requests.get(url)           #requests的含的get方法
        if response.status_code == 200:        #.status_code 表示 状态码。 状态码200 表示发送请求成功
            print(len(response.text))
    return spider_inner
r=spider_outer('https://www.cnblogs.com/xiaoyuanqujing/')
r()

 

4.闭包函数的应用:为了装饰器作准备

5.闭包函数的作用:从外部读取局部变量

 

def f1():
    number = 100
    def f2():                   #在这里f2是闭包
        print(number)
    return f2                   #将f2地址返回给函数f1()
func = f1()                     #将f1() 它表示地址赋值给func
func()                          #调用函数

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们就可以在f1外部读取它的内部变量了.

三、装饰器

不修改被装饰对象的源代码
不修改被装饰对象的调用方式

被装饰对象: ---> 需要添加功能 函数
装饰器: ---> 被装饰对象添加的新功能的 函数

 1.定义:在不修改装饰对象源代码与调用方式的前提下,添加新的功能
遵循的原则:开放封闭。
开放:对现有功能的扩展开放
封闭:已实现的功能代码块不能被修改
2.装饰器的作用:
统计时间
登录认证
3.为什么使用装饰器:
可以解决代码冗余问题,提高代码的可扩展性。
4.编写装饰器
例子1:被装饰对象:无参数,有返回值
import time
def download_movie():
    print('开始下载电影...')
    time.sleep(3)
    print('电影下载成功...')
    return '小泽.mp4'
def time_record(func):              # func <-- download_movie
    def inner():
        start_time = time.time()
        res = func()
        end_time = time.time()
        print(f'消耗时间: {end_time - start_time}')
        return res
    print(inner())
    return inner                  #表示把 inner的地址返回给time_record()函数
time_record(download_movie)()     #time_record(download_movie)表示接受inner的地址,后面的()表示调用函数
import time
def download_movie():
    print('开始下载电影...')
    time.sleep(3)
    print('电影下载成功...')
    return '小泽.mp4'
def time_record(func):  # func <-- download_movie
    def inner():
        start_time = time.time()
        res = func()
        end_time = time.time()
        print(f'消耗时间: {end_time - start_time}')
        return res
    print(inner())
    return inner                 #表示把 inner的地址返回给time_record()函数
# time_record(download_movie)()    #time_record(download_movie)表示接受inner的地址,后面的()表示调用函数
download_movie=time_record(download_movie)
download_movie()

例子2:被装饰对象:有参数,有返回值

import time
def download_movie(url):
    print(f'{url}中的电影开始下载了...')
    time.sleep(3)
    print('电影下载成功...')
    return '小泽.mp4'
def time_record(func):
    def inner(url):
        start_time = time.time()
        res = func(url)                                     # 这里func()中的参数是从inner中拿的
        end_time = time.time()
        print(f'消耗时间: {end_time - start_time}')
        return res
    return inner
t = time_record(download_movie)                              # time_record(download_movie) 表示给time_record()函数传download_movie实参
t('https://www.cnblogs.com/xiaoyuanqujing/')

例子3: 被装饰对象,需要接收多个参数

import time
def download_movie(*args, **kwargs):
    print('电影开始下载了...')
    time.sleep(3)
    print('电影下载成功...')
    return '小泽.mp4'
def time_record(func):
    def inner(*args, **kwargs):                         # *args, **kwargs接收所有参数
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print(f'消耗时间: {end_time - start_time}')
        return res
    return inner
download_movie = time_record(download_movie)
download_movie(url1='https://www.baidu.com', url2='url2', url3='url3')

 四、

@: 装饰器的语法糖

        @wrapper 

         注意: 在使用装饰器语法糖时,装饰器必须定义在被装饰对象之上。

五、装饰器模板

def wrapper(func):
    def inner(*args, **kwargs):
        # 添加新功能    
            res = func(*args, **kwargs)
#添加新功能
return resreturn inner def func1(): pass func1 = wrapper(func1) func1() # inner(

 

 

posted @ 2019-11-12 18:23  薛定谔的猫66  阅读(266)  评论(0)    收藏  举报