zoukankan      html  css  js  c++  java
  • 函数对象、函数嵌套、名称空间与作用域、装饰器

    一 函数对象

    一 函数是第一类对象,即函数可以当作数据传递

    #1 可以被引用
    #2 可以当作参数传递
    #3 返回值可以是函数
    #3 可以当作容器类型的元素

    二 利用该特性,优雅的取代多分支的if

    复制代码
    def foo():
        print('foo')
    
    def bar():
        print('bar')
    
    dic={
        'foo':foo,
        'bar':bar,
    }
    while True:
        choice=input('>>: ').strip()
        if choice in dic:
            dic[choice]()
    复制代码

    二 函数嵌套

    一 函数的嵌套调用

    复制代码
    def max(x,y):
        return x if x > y else y
    
    def max4(a,b,c,d):
        res1=max(a,b)
        res2=max(res1,c)
        res3=max(res2,d)
        return res3
    print(max4(1,2,3,4))
    复制代码

    二 函数的嵌套定义

    复制代码
    def f1():
        def f2():
            def f3():
                print('from f3')
            f3()
        f2()
    
    f1()
    f3() #报错,为何?请看下一小节
    复制代码

    三 名称空间与作用域

    一 什么是名称空间?

    #名称空间:存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)

    二 名称空间的加载顺序

    python test.py
    #1、python解释器先启动,因而首先加载的是:内置名称空间
    #2、执行test.py文件,然后以文件为基础,加载全局名称空间
    #3、在执行文件的过程中如果调用函数,则临时产生局部名称空间

    三 名字的查找顺序

    复制代码
    局部名称空间--->全局名称空间--->内置名称空间
    
    #需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例
    
    # max=1
    def f1():
        # max=2
        def f2():
            # max=3
            print(max)
        f2()
    f1()
    print(max) 
    复制代码

    四 作用域

    View Code

    五 global与nonlocal关键字

    四 闭包函数

    一 什么是闭包?

    复制代码
    #内部函数包含对外部作用域而非全局作用域的引用
    
    #提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来喽,包起呦,包起来哇
    
            def counter():
                n=0
                def incr():
                    nonlocal n
                    x=n
                    n+=1
                    return x
                return incr
    
            c=counter()
            print(c())
            print(c())
            print(c())
            print(c.__closure__[0].cell_contents) #查看闭包的元素
    复制代码

    二 闭包的意义与应用

    复制代码
    #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
    #应用领域:延迟计算(原来我们是传参,现在我们是包起来)
        from urllib.request import urlopen
    
        def index(url):
            def get():
                return urlopen(url).read()
            return get
    
        baidu=index('http://www.baidu.com')
        print(baidu().decode('utf-8'))
    复制代码

    五 装饰器

    装饰器就是闭包函数的一种应用场景

    一 为何要用装饰器

    #开放封闭原则:对修改封闭,对扩展开放

    二 什么是装饰器

    装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
    强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
    装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

    三 装饰器的使用

    无参装饰器
    有参装饰器

    四 装饰器语法

    复制代码
    被装饰函数的正上方,单独一行
            @deco1
            @deco2
            @deco3
            def foo():
                pass
    
            foo=deco1(deco2(deco3(foo)))
    复制代码

    五 装饰器补充:wraps

    复制代码
    from functools import wraps
    
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper
    
    @deco
    def index():
        '''哈哈哈哈'''
        print('from index')
    
    print(index.__doc__)
    复制代码

    六 练习题

    一:编写函数,(函数执行的时间是随机的)
    二:编写装饰器,为函数加上统计时间的功能
    三:编写装饰器,为函数加上认证的功能

    四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
    注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式

    五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录

    六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

    七:为题目五编写装饰器,实现缓存网页内容的功能:
    具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

    扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中

    八:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作

    九 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定
    注意:时间格式的获取
    import time
    time.strftime('%Y-%m-%d %X')

    View Code
  • 相关阅读:
    CDH 2、Cloudera Manager的安装
    204 01 Android 零基础入门 03 Java常用工具类 04 Java集合 04 Map集合 01 Map概述
    203 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 07 删除宠物猫信息数据(引入泛型知识点)
    202 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 06 查找宠物猫信息数据
    201 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 05 添加重复的宠物猫信息数据
    200 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 04 添加和显式宠物猫信息
    199 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 03 宠物猫信息管理概述
    198 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 02 案例:在集合中插入字符串
    197 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 01 Set概述
    196 01 Android 零基础入门 03 Java常用工具类 04 Java集合 02 List集合 05 案例:公告的删除和修改
  • 原文地址:https://www.cnblogs.com/fuyuteng/p/9035172.html
Copyright © 2011-2022 走看看