本文档内容:

1 python中三种名称空间和作用域

2 函数的使用

3 闭包

4 装饰器

一 python中三种名称空间和作用域

1.1名称空间:

  1. 当程序运行时,代码从上至下依次执行,它会将变量与值得关系存储在一个空间中,这个空间
  2. 也叫命名空间。例如:name='xingchen'
  3. 当程序遇到函数时,它会将函数名存在内存中,函数内部的变量和逻辑暂时不关心;
  4. 当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),这个空间叫临时名称空间
  5. 也叫局部名称空间。
  6. 函数外面访问不到临时空间的内容;随着函数的执行完毕,临时空间会释放掉。

python中名称空间分三种:
  内置名称空间
  全局名称空间
  局部名称空间
作用域:
  全局作用域:
    内置名称空间
    全局名称空间
局部作用域:
    局部名称空间
加载顺序
内置名称空间 ---》全局名称空间(程序执行时) ---》局部名称空间(函数执行时)
取值顺序:单向不可逆
局部名称空间 ---》全局名称空间 ----》内置名称空间

1.2  globals和locals

print(globals() ) 返回的是全局作用域里面的变量与其值,是一个字典

print(locals())   返回的是当前的局部变量与其值,也是一个字典

例如:

  1. def func1():
  2. a=1
  3. print(a)
  4. print(locals())
  5. print(globals())
  6. func1()

其结果为:

  1. 1
  2.  
  3. {'a':}
  4.  
  5. {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000024FD014B240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/PycharmProjects-x/s22day03/day4/lianxi.py', '__cached__': None, 'time': <module 'time' (built-in)>, 'func1': <function func1 at 0x0000024FD0056048>}

1.3 global和nonlocal

global:声明一个全局变量,可以用作局部变量的关键字来修改或赋值给全局变量,

    但是:对可变数据类型(list,dict,set)可以直接引用不用通过global。如果默认参数是一个可变的数据类型,那么他在内存中永远是一个

例如:下面的list就是可变数据类型,因此就不用global

  1. # def extendList(val,list=[]):
  2. #    list.append(val)
  3. #    return list
  4. # list1 = extendList(10)
  5. # print('list1=%s'%list1) # [10,]
  6. # list2 = extendList(123,[])
  7. # print('list2=%s'%list2) # [123,]
  8. # list3 = extendList('a')
  9. # print('list3=%s'%list3) #[10,'a']
  10.  
  11. # print('list1=%s'%list1)
  12. # print('list2=%s'%list2)
  13. # print('list3=%s'%list3)
  14.  
  15. 其结果为:
  16.  
  17. [10,a]
  18.  
  19. [123]
  20.  
  21. [10,a]

nonlocal:在局部作用域中,对其父级作用域(或者更外层作用域)进行变量赋值或者修改,但是不能修改全局作用域

例如:

  1. def func1():
  2. a=1
  3. def func2():
  4. b=10
  5. def func3():
  6. nonlocal a,b
  7. a=a+1
  8. b=b+1
  9. print(a,b) #结果为 2,11
  10. func3()
  11. print(a,b) #结果为 2,11,func2函数的b被引用了
  12. func2()
  13. print(a)        #结果为 2,这里的变量a被引用了,但是b不是在这里面引用的,所以打印b会报错
  14. func1()

二函数的使用

函数名的本质就是函数的内存地址

1 函数可以被引用

例如:

  1. def func1():
  2. print('in func1')
  3. f=func1
  4. print(f)
  5. 结果为:<function func1 at 0x000001E9313C6048>

2 函数可以作为容器类元素

例如

  1. def func1():
  2. print('f1')
  3.  
  4. def func2():
  5. print('f2')
  6.  
  7. l1=[func1,func2]
  8. l2={'f1':func1,'f2':func2}
  9.  
  10. l1[0]()
  11. l2['f2']()

3 函数可以作为返回值

  1. def f1():
  2. print('f1')
  3.  
  4. def func1(argv):
  5. argv()
  6. return argv
  7.  
  8. f = func1(f1)
  9. f()

其他: 第一类对象

  1. 第一类对象(first-class object)指
  2. 1.可在运行期创建
  3. 2.可用作函数参数或返回值
  4. 3.可存入变量的实体。

三 闭包

内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数,一般用于装饰器或者网络爬取内容

判断闭包函数的方法__closure__

例如:

  1. def func():
  2. name = 'eva'
  3. def inner():
  4. print(name)
  5.      print(inner.__closure__) #结果中函数含有cell元素,否则为none
  6. return inner
  7. f = func()
  8. f()

闭包函数一个例子

  1. def line_conf(a, b):
  2. def line(x):
  3. return a * x + b
  4. return line

四 装饰器

装饰器的本质是一个python函数,基于闭包函数,让其他的函数在不改变源码和调用方式的前提下,增加新的功能

  装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。

下面看看装饰器的形成过程:

原始的代码

  1. import time
  2. # print(time.time()) # 1527326532.2688255
  3.  
  4. # def func1():
  5. #   time.sleep(0.3)
  6. #    print('非常复杂......')
  7. #
  8. # start_time = time.time()
  9. # func1()
  10. # end_time = time.time()
  11. # print('此函数的执行效率%s' %(end_time-start_time))

# 改版1:我要封装到一个函数中

  1. # def func1():
  2. #    time.sleep(0.3)
  3. #    print('非常复杂......')
  4. #
  5. # def func2():
  6. #    time.sleep(0.3)
  7. #    print('特别复杂......')
  8. #
  9. # func1()
  10. # func2()

# # 改版2:被测试函数当参数传入,可以测试多个函数的执行效率

  1. # def timmer(f):
  2. #    start_time = time.time()
  3. #   f()
  4. #    end_time = time.time()
  5. #    print('此函数的执行效率%s' %(end_time-start_time))
  6. #
  7. # timmer(func1)
  8. # timmer(func2)

# 改版3::测试函数执行效率的同时,不要改变原函数的调用方式。

  1. # def func1():
  2. #   time.sleep(0.3)
  3. #   print('非常复杂......')
  4. # def func2():
  5. #    time.sleep(0.3)
  6. #    print('特别复杂......')
  7. # # func1()
  8. # # func2()
  9. # def timmer(f):
  10. #    start_time = time.time()
  11. #   f()
  12. #   end_time = time.time()
  13. #    print('此函数的执行效率%s' % (end_time - start_time))
  14. # f1 = func1
  15. # func1 = timmer #
  16. # func1(f1) # timmer(func1)

# 改版4::改版3虽然大体上满足了我的要求,但是增加两行代码,
# 而且多了参数,不好,继续改,尽量不添加其他代码,而且做到调用时一模一样
# 最简单的装饰器。

  1. # def func1():
  2. #   time.sleep(0.3)
  3. #    print('非常复杂......')
  4. # def func2():
  5. #    time.sleep(0.3)
  6. #    print('特别复杂......')
  7. # # func1()
  8. # # func2()
  9. #
  10. # def timmer(f): # f = func1 函数名
  11. #    def inner():
  12. #     start_time = time.time()
  13. #      f()
  14. #      end_time = time.time()
  15. #     print('此函数的执行效率%s' % (end_time - start_time))
  16. #    return inner
  17. #
  18. # func1 = timmer(func1) # inner
  19. # func2 = timmer(func2) # inner
  20. # func1() # inner()
  21. # func2()

# 改版5::改版4每次测试一个函数的执行效率时,都需要加一行 func1 = timmer(func1)代码,麻烦
# python提出了一个语法糖 @。

  1. # def timmer(f): # f = func1 函数名
  2. #    def inner():
  3. #       start_time = time.time()
  4. #       f()
  5. #       end_time = time.time()
  6. #       print('此函数的执行效率%s' % (end_time - start_time))
  7. #    return inner
  8. #
  9. # @timmer # func1 = timmer(func1) inner
  10. # def func1():
  11. #    time.sleep(0.3)
  12. #    print('非常复杂......')
  13. #
  14. # func1() # inner()

# 改版6:被装饰的函数肯定要有参数的,你现在不能满足,解决这个问题。
# 被装饰的函数带参数的装饰器

  1. # def timmer(f): # f = func1 函数名
  2. #    def inner(*args,**kwargs): # args = (1,2),kwargs {sex:'nv',name:'alex'}
  3. #       start_time = time.time()
  4. #     f(*args,**kwargs) # f(1,2,,sex='nv',name='alex')
  5. #      end_time = time.time()
  6. #       print('此函数的执行效率%s' % (end_time - start_time))
  7. #    return inner
  8. #
  9. # @timmer # func1 = timmer(func1) inner
  10. # def func1(a,b):
  11. #    time.sleep(0.3)
  12. #    print(a,b)
  13. #    print('非常复杂......')
  14. #
  15. #
  16. # @timmer # func1 = timmer(func1) inner
  17. # def func2(a,b,name,sex='man'): # f(1,2,,sex='nv',name='alex')
  18. #    time.sleep(0.3)
  19. #    print(a,b,sex,name)
  20. #    print('非常复杂......')
  21. #
  22. # func2(1,2,sex='nv',name='alex') # inner()

# 改版7:被装饰的函数肯定要有返回值的,解决这个问题。
# 被装饰的函数带参数且有返回值的装饰器

  1. # def timmer(f): # f = func2 函数名
  2. #    def inner(*args,**kwargs): # args = (1,2),kwargs {sex:'nv',name:'alex'}
  3. #       start_time = time.time()
  4. #     ret = f(*args,**kwargs) # f(1,2,,sex='nv',name='alex')
  5. #       end_time = time.time()
  6. #       print('此函数的执行效率%s' % (end_time - start_time))
  7. #      return ret
  8. #   return inner
  9. # @timmer # func1 = timmer(func1) inner
  10. # def func2(a,b,name,sex='man'): # f(1,2,,sex='nv',name='alex')
  11. #    time.sleep(0.3)
  12. #   print(a,b,sex,name)
  13. #    print('非常复杂......')
  14. #    return 666
  15. #
  16. # print(func2(1,2,sex='nv',name='alex')) # inner()
  17.  
  18. def timmer(f):
  19.   def inner(*args,**kwargs):
  20.     start_time = time.time()
  21.     ret = f(*args,**kwargs)
  22.     end_time = time.time()
  23.     print('此函数的执行效率%s' % (end_time - start_time))
  24.     return ret
  25.   return inner
  26. @timmer
  27. # def func2(a,b,name,sex='man'):
  28. #    time.sleep(0.3)
  29. #    print(a,b,sex,name)
  30. #    print('非常复杂......')
  31. #    return 666
  32. #
  33. # ret1 = func2(1,2,sex='nv',name='alex')
  34. # print(ret1)
  1. 至此装饰器的固定结构如下
  1. def timer(func):
  2. def inner(*args,**kwargs):
  3. '''执行函数之前要做的'''
  4. re = func(*args,**kwargs)
  5. '''执行函数之后要做的'''
  6. return re
  7. return inner

但是如何函数有很多,如何取消他们呢,以后如果又加上呢---带参数的装饰器模型

  1. def outer(flag):
  2. def timer(func):
  3. def inner(*args,**kwargs):
  4. if flag:
  5. print('''执行函数之前要做的''')
  6. re = func(*args,**kwargs)
  7. if flag:
  8. print('''执行函数之后要做的''')
  9. return re
  10. return inner
  11. return timer
  12.  
  13. @outer(False) #改为false是不执行装饰器内的内容
  14. def func():
  15. print(111)
  16.  
  17. func()

如果多个装饰器装饰一个函数呢

  1. def wrapper1(func):
  2. def inner():
  3. print('wrapper1 ,before func')
  4. func()
  5. print('wrapper1 ,after func')
  6. return inner
  7.  
  8. def wrapper2(func):
  9. def inner():
  10. print('wrapper2 ,before func')
  11. func()
  12. print('wrapper2 ,after func')
  13. return inner
  14.  
  15. @wrapper1
  16. @wrapper2
  17. def f():
  18. print('in f')
  19. f()

其结果为:

  1. wrapper1 ,before func
  2. wrapper2 ,before func
  3. in f
  4. wrapper2 ,after func
  5. wrapper1 ,after func

装饰器的另外一种方法:

  1. import functools
  2. def wrapper(func):
  3. @functools.wraps(func)
  4. def inner(*args, **kwargs):
  5. print('我是装饰器')
  6. return func(*args,**kwargs)
  7. print('--------')
  8. return inner
  9.  
  10. @wrapper
  11. def index():
  12. print('我是被装饰函数')
  13. return None
  14.  
  15. index()

---------------------------------------------------------------------------------回顶部----------------------------------------------------------------------------------------------------------------------------

day4----函数-闭包-装饰器的更多相关文章

  1. python函数闭包-装饰器-03

    可调用对象 callable()  # 可调用的(这个东西加括号可以执行特定的功能,类和函数) 可调用对象即  callable(对象)  返回为  True  的对象 x = 1 print(cal ...

  2. 【Python3的命名空间与作用域,闭包函数,装饰器】

    一.命名空间与作用域 命名空间是名字和对象的映射,就像是字典,key是变量名,value是变量的值 1.命名空间的定义 name='egon' #定义变量 def func(): #定义函数 pass ...

  3. python学习笔记-day4笔记 常用内置函数与装饰器

    1.常用的python函数 abs             求绝对值 all               判断迭代器中所有的数据是否为真或者可迭代数据为空,返回真,否则返回假 any          ...

  4. Python之函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器

    目录 一 函数对象 二 函数的嵌套 三 名称空间和作用域 四 闭合函数 五 装饰器 一.函数对象 1.函数是第一类对象 #第一类对象的特性:# 可以被引用 # 可以当做参数传递 # 返回值是函数 # ...

  5. day11 闭包函数和装饰器

    1.函数不是新知识点 主要是学习函数的用法 在面向对象编程中,一切皆对象,函数也不例外 具体的表现 1.函数可以引用 2.函数可以作为函数的参数 3.函数可以作为函数的返回值 4.可以被存储到容器类型 ...

  6. python基础-闭包函数和装饰器

    闭包函数和装饰器 闭包函数 概念:在函数中(嵌套)定义另一个函数时,内部函数引用了外层函数的名字. 特性 闭包函数必须在函数内部定义 闭包函数可引用外层函数的名字 闭包函数是函数嵌套.函数对象.名称空 ...

  7. day11_7.11 闭包函数与装饰器

    补充: callable 代表可调用的,加括号可以执行.(函数或者类) import this  查看python之禅 一.闭包函数 所谓闭包函数,就是定义在函数内部的函数,也就是函数定义的嵌套.而在 ...

  8. CSIC_716_20191112【闭包函数和装饰器】

    闭包函数 什么是闭包函数:闭包函数是函数嵌套.函数对象.名称空间和作用域的集合体. 闭包函数必须在函数内部定义,闭包函数可以引用外层函数的名字. # _*_ coding: gbk _*_ # @Au ...

  9. Python_oldboy_自动化运维之路_函数,装饰器,模块,包(六)

    本节内容 上节内容回顾(函数) 装饰器 模块 包 1.上节内容回顾(函数) 函数 1.为什么要用函数? 使用函数之模块化程序设计,定义一个函数就相当于定义了一个工具,需要用的话直接拿过来调用.不使用模 ...

  10. python学习之路-4 内置函数和装饰器

    本篇涉及内容 内置函数 装饰器 内置函数 callable()   判断对象是否可以被调用,返回一个布尔值 1 2 3 4 5 6 7 8 9 10 11 num = 10 print(callabl ...

随机推荐

  1. R3注入的四种方式

    DLL注入 1.首先要获取想要注入的进程句柄(OpenProcess) 2.从要注入的进程的地址空间中分配一段内存(VirtualAllocEx) 3.往分配的内存位置写入要注入的DLL名称(Writ ...

  2. Linux下批处理文件编写

    linux下的批处理文件,基本就是shell脚本文件. 一.最简单的脚本书写方法为: 1.新建一个文件,名字为test(自己定义的名字) touch test.sh 2.在里面编写脚本 程序必须以下面 ...

  3. elasticsearch 聚合函数 max double精度损失bug

    测试样例数据{ "size" : 0, "query" : { "bool" : { "must" : { " ...

  4. AXI Quad SPI

    AXI Quad SPI 信息来源

  5. c++中计算程序执行时间

    #include<iostream> #include<time.h> using namespace std; int main() { clock_t t1 = clock ...

  6. PI接口无法使用.net4以上的解决方法:无法嵌入互操作类型“PISDKClass”。请改用适用的接口。

    Interop type 'PISDKClass' cannot be embedded. Use the applicable interface instead. .net开发中,有时候在引用某些 ...

  7. python之全局安装包管理工具pip

    1.curl 'https://bootstrap.pypa.io/get-pip.py' > get-pip.py 2.sudo python get-pip.py 3.sudo easy_i ...

  8. Js之事件循环(执行机制)

    js的执行机制是事件循环 什么是事件循环? js引擎在执行代码时,首先会将同步代码加入到主线程中,异步代码会放到event table中注册回调函数, 当主线程空闲之后,event table中的回调 ...

  9. IE10 下系统出现Unable to get property 'PageRequestManager' of undefined or null reference错误

    在本地调试时没有任何问题,上传到测试服务器(win2003 framework 4.0)后打开网站出现Unable to get property 'PageRequestManager' of un ...

  10. [ZZ]面向对象编程,再见!

    面向对象编程,再见!- 机器学习算法与自然语言处理 https://mp.weixin.qq.com/s/icXBlVOOYLvDnER7cEeCeg https://medium.com/@csca ...