博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
函数(二)--函数对象、函数嵌套、名称空间与作用域、装饰器
阅读量:5308 次
发布时间:2019-06-14

本文共 5146 字,大约阅读时间需要 17 分钟。

一 、函数对象

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

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

2、利用该特性,优雅的取代多分支的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]()

二 、函数嵌套

1、函数的嵌套调用

def max(x,y):    return x if x > y else ydef max4(a,b,c,d):    res1=max(a,b)    res2=max(res1,c)    res3=max(res2,d)    return res3print(max4(1,2,3,4))

2、函数的嵌套定义

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

三、 名称空间与作用域

1、名称空间

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

2、 名称空间的加载顺序

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

3、 名字的查找顺序

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

4、作用域

#1、作用域即范围  - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效  - 局部范围(局部名称空间属于该范围):临时存活,局部有效#2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下x=1def f1():    def f2():        print(x)    return f2x=100def f3(func):    x=2    func()x=10000f3(f1())#3、查看作用域:globals(),locals()LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__locals 是函数内的名字空间,包括局部变量和形参enclosing 外部嵌套函数的名字空间(闭包中常见)globals 全局变量,函数定义所在模块的名字空间builtins 内置模块的名字空间

5、global与nonlocal关键字

global适用于函数内部修改全局变量的值nonlocal适用于嵌套函数中内部函数修改外部变量的值如果没有使用以上关键字,对全局变量或者外部变量进行修改,python会默认将全局变量隐藏起来例1:def outside():  var = 5  def inside():    var = 3    print(var)  inside()outside()例2:def outside():  var = 5  def inside():    print(var)  inside函数改变了var所以python将var隐藏了起来,这里的print找不到var因而报错。    var = 3  inside()outside()例1不会显示报错,但是例2会
global与nonlocal关键字总结

四、 闭包函数

1、闭包

#内部函数包含对外部作用域而非全局作用域的引用#提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来喽,包起呦,包起来哇        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) #查看闭包的元素

2、闭包的意义与应用

#闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域#应用领域:延迟计算(原来我们是传参,现在我们是包起来)    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 不修改被装饰对象的调用方式装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

3、 装饰器的使用

import timedef timmer(func):    def wrapper(*args,**kwargs):        start_time=time.time()        res=func(*args,**kwargs)        stop_time=time.time()        print('run time is %s' %(stop_time-start_time))        return res    return wrapper@timmerdef foo():    time.sleep(3)    print('from foo')foo()
无参装饰器
def auth(driver='file'):    def auth2(func):        def wrapper(*args,**kwargs):            name=input("user: ")            pwd=input("pwd: ")            if driver == 'file':                if name == 'pie' and pwd == '123':                    print('login successful')                    res=func(*args,**kwargs)                    return res            elif driver == 'ldap':                print('ldap')        return wrapper    return auth2@auth(driver='file')def foo(name):    print(name)foo('pie')
有参装饰器

4、 装饰器语法

被装饰函数的正上方,单独一行        @deco1        @deco2        @deco3        def foo():            pass        foo=deco1(deco2(deco3(foo)))
# 有参装饰器的模板def outter1(x,y,z):    def outter2(func):        def wrapper(*args,**kwargs):            res=func(*args,**kwargs)            return res        return wrapper    return outter2# 无参装饰器的模板def outter(func):    def wrapper(*args,**kwargs):        res=func(*args,**kwargs)        return res    return wrapper
装饰器模板

5、 装饰器补充:wraps

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

6、 叠加多个装饰器

# 叠加多个装饰器# 1. 加载顺序(outter函数的调用顺序):自下而上# 2. 执行顺序(wrapper函数的执行顺序):自上而下
def outter1(func1): #func1=wrapper2的内存地址    print('加载了outter1')    def wrapper1(*args,**kwargs):        print('执行了wrapper1')        res1=func1(*args,**kwargs)        return res1    return wrapper1def outter2(func2): #func2=wrapper3的内存地址    print('加载了outter2')    def wrapper2(*args,**kwargs):        print('执行了wrapper2')        res2=func2(*args,**kwargs)        return res2    return wrapper2def outter3(func3): # func3=最原始的那个index的内存地址    print('加载了outter3')    def wrapper3(*args,**kwargs):        print('执行了wrapper3')        res3=func3(*args,**kwargs)        return res3    return wrapper3@outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址@outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址@outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址def index():    print('from index')print('======================================================')index()示范代码
示范代码

 

转载于:https://www.cnblogs.com/zhangbingsheng/p/10109529.html

你可能感兴趣的文章
Django 模型层
查看>>
dedecms讲解-arc.listview.class.php分析,列表页展示
查看>>
Extjs6 经典版 combo下拉框数据的使用及动态传参
查看>>
【NodeJS】http-server.cmd
查看>>
研磨JavaScript系列(五):奇妙的对象
查看>>
面试题2
查看>>
selenium+java iframe定位
查看>>
P2P综述
查看>>
第五章 如何使用Burp Target
查看>>
Sprint阶段测试评分总结
查看>>
sqlite3经常使用命令&语法
查看>>
linux下编译openjdk8
查看>>
【python】--迭代器生成器装饰器
查看>>
Pow(x, n)
查看>>
安卓当中的线程和每秒刷一次
查看>>
每日一库:Modernizr.js,es5-shim.js,es5-safe.js
查看>>
ajax连接服务器框架
查看>>
wpf样式绑定 行为绑定 事件关联 路由事件实例
查看>>
利用maven管理项目之POM文件配置
查看>>
TCL:表格(xls)中写入数据
查看>>