补充:全局变量声明及局部变量引用

python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量

global关键字用来在函数或其他局部作用域中使用全局变量,声明后可以在其他作用于中修改和使用

  1. x=1      #全局赋值变量
  2. def foo():
  3. global x    #函数内部全局声明变量x
  4. x=1111111    #函数内部修改全局变量x
  5. print(x)
  6. foo()
  7. print(x

global声明的变量在任何作用域都能够修改,所以一般非必要情况下要避免这种声明操作。

nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量,一般用在函数嵌套。

  1. def f1():
  2. # x=2
  3. def f2():
  4. x=3
  5. def f3():
  6. nonlocal x
  7. x=1111
  8. # print('f3',x)
  9. f3()
  10. print('f2',x)
  11. f2()
  12. # print('f1',x)
  13. f1()

如上,如果在f3的函数体内部不做nonlocal声明x,即将nonlocal x注释掉,那么函数体f2内的print将打印的结果是“f2 3”,声明后的结果为“f2 1111”。

闭包函数

闭包函数定义:

函数内部定义的函数称为内部函数,该内部函数包含对外部(上层)作用域,而不是对全局作用域名字的,那么该内部函数称为闭包函数

定义闭包函数:

  1. 定义闭包函数的基本形式
  2. def 外部函数名():
  3. 内部函数需要的变量
  4. def 内部函数(): #基本函数
  5. 引用外部的变量
  6. return 内部函数 #不加括号,返回内存地址

闭包函数指的是内部函数

闭包函数包含对外部作用域的引用,而非全局作用域的引用

闭包函数的特点:自带向外的作用域,延迟计算(惰性计算,用到的时候计算)

示例:

  1. name='alex'    #全局定义的变量
  2. def func():    
  3. name='egon'  #函数func调用的变量,外部作用域
  4. def bar():    #内部函数
  5. print(name)  #内部函数bar打印name的作用域除了bar函数自己本身,还有func函数内部
  6. return bar    #调用func函数时的返回值为bar函数本身,而非bar函数执行结果,返回的是bar函数的一段内存地址
  7. b=func()      #b接收func函数的返回值,即bar函数的内存空间,现在的b就等于是bar
  8. print(b)
  9. b()        #执行b即执行bar函数的print(name)打印操作,而非全局定义的name
  10. #print(b.__closure__[0].cell_contents) #返回作用域空间的第一个变量值
  11. #print(b.__closure__) #作用域空间信息
  12.  
  13. 输出结果
  14. <function func.<locals>.bar at 0x0000021CA66CB8C8>
  15. egon

自带向外的作用域,即bar函数包含func函数的作用域,也包含bar本身的作用域,即bar能够调用name='egon'

作用域在函数定义的时候已经固定了,也就是说,无论在什么地方调用b(),b函数的作用域永远用的是bar函数定义时候的作用域。

装饰器基础

程序源代码的原则:对功能扩展开放,对修改源代码封闭

即可以在源代码的基础上扩展功能,而不能修改源代码(原因是,系统上线了修改源代码,改错了咋整)

装饰器就是用来进行源代码功能能扩展的一种实现方式。

装饰器本质上是任意可调用的对象,目前能够理解的就是是函数,而被装饰的对象也可以是任意可调用的对象。

装饰器功能:是在不修改被装饰对象源代码以及被装饰对象的调用方式的前提下,为其添加新功能

装饰器原则:不修改源代码,不修改调用方式,还要能够增加新功能

示例一:当调用函数index时候,随机等待0-4秒打印hello world

  1. #原功能
  2. import time
  3. import random
  4. def index():
  5. time.sleep(random.randrange(1,5))
  6. print('hello world')
  7. index()

示例二:扩展功能统计index的执行时间,包括随机等待的时间

  1. import time
  2. import random
  3.  
  4. def index_new(func):
  5. def timmer():
  6. start_time=time.time()
  7. func()
  8. stop_time=time.time()
  9. print('time:%s' %(stop_time-start_time))
  10. return timmer
  11.  
  12. def index():    #源代码并不改变
  13. time.sleep(random.randrange(1,5))
  14. print('hello world')
  15.  
  16. index=index_new(index)
  17. index()
  18.  
  19. 输出结果:
  20. hello world
  21. time:3.000032663345337

示例三:装饰器调用语法

  1. def index_new(func):
  2. def timmer():
  3. start_time=time.time()
  4. func()
  5. stop_time=time.time()
  6. print('time:%s' %(stop_time-start_time))
  7. return timmer
  8. #使用@符号进行调用
  9. @index_new #index=index_new(index)
  10. def index():
  11. time.sleep(random.randrange(1,5))
  12. print('hello world')
  13.  
  14. index()

示例四:定义多个装饰器,增加多个功能模块

  1. import time
  2. import random
  3. #装饰器1:计时模块
  4. def timmer(func):
  5. def wrapper():
  6. start_time = time.time()
  7. func()
  8. stop_time=time.time()
  9. print('run time is %s' %(stop_time-start_time))
  10. return wrapper
  11. #装饰器2:认证模块
  12. def auth(func):
  13. def deco():
  14. name=input('name: ')
  15. password=input('password: ')
  16. if name == 'egon' and password == '123':
  17. print('login successful')
  18. func() #wrapper()
  19. else:
  20. print('login err')
  21. return deco
  22.  
  23. #被装饰函数
  24. @auth #index=auth(wrapper) #index=deco #index=auth(wrapper) #index=deco
  25. @timmer #index=timmer(index) #index=wrapper
  26. def index():
  27. # time.sleep(random.randrange(1,5))
  28. time.sleep(3)
  29. print('welecome to index page')
  30.  
  31. #并没有调用任何装饰器
  32. def home():
  33. time.sleep(random.randrange(1,3))
  34. print('welecome to HOME page')
  35.  
  36. index() #deco()
  37. home()

当要调用多个装饰器的时候,调用的顺序是,谁先执行就先调用哪一个,顺序是从上而下,但是内部计算的顺序是从下而上的

示例五:源代码需要传入参数的,以及需要返回值的

  1. import time
  2. import random
  3. #装饰器
  4. def timmer(func):
  5. def wrapper(*args,**kwargs):  #*args和**kwargs能够接收任意的参数,并且可以不存在,接收后原封不动传入到func调用的函数
  6. start_time = time.time()
  7. res=func(*args,**kwargs)    #返回值赋值,需要传入的函数有返回值才行
  8. stop_time=time.time()
  9. print('run time is %s' %(stop_time-start_time))
  10. return res    #抛出返回值
  11. return wrapper
  12. #被装饰函数
  13.  
  14. @timmer
  15. def index():
  16. time.sleep(random.randrange(1,5))
  17. print('welecome to index page')
  18. @timmer
  19. def home(name):
  20. time.sleep(random.randrange(1,3))
  21. print('welecome to %s HOME page' %name)
  22. return 123123123123123123123123123123123123123123
  23.  
  24. res1=index()
  25. print('index return %s' %res1)
  26. res2=home('egon') #wraper()
  27. print('home return %s' %res2)

python基础之闭包函数和装饰器的更多相关文章

  1. Python基础(7)闭包函数、装饰器

    一.闭包函数 闭包函数:1.函数内部定义函数,成为内部函数, 2.改内部函数包含对外部作用域,而不是对全局作用域名字的引用 那么该内部函数成为闭包函数 #最简单的无参闭包函数 def func1() ...

  2. Python基础(闭包函数、装饰器、模块和包)

    闭包函数 格式: def 函数名1(): def 函数名2(): 变量 = 值 return 变量 return 函数名2 func = 函数名1() key = func()

  3. python基础之闭包函数与装饰器

    闭包函数: 什么是闭包函数: 闭指的是定义在一个函数内部 包指的是该函数包含对外部作用域(非全局作用域)名字的引用 def counter(): n=0 def incr(): nonlocal n ...

  4. python 基础篇 11 函数进阶----装饰器

    11. 前⽅⾼能-装饰器初识本节主要内容:1. 函数名的运⽤, 第⼀类对象2. 闭包3. 装饰器初识 一:函数名的运用: 函数名是一个变量,但他是一个特殊变量,加上括号可以执行函数. ⼆. 闭包什么是 ...

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

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

  6. day11 闭包函数和装饰器

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

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

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

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

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

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

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

随机推荐

  1. Java Knowledge series 2

    JVM Analysis & Design The object-oriented paradigm is a new and different way of thingking about ...

  2. 【Android学习入门】Android studio基本设置

    1.背景设置 依次选择File->Settings-->Appearance & Behaviour->Apprearance,然后勾选 show line number. ...

  3. android listview 加载遇到的问题

    http://blog.csdn.net/l_serein/article/details/7706338 转载: 描述一下场景: 菜单栏上有若干分类,点击每一个分类,ListView下分根据分类显示 ...

  4. [原创] Debian9上配置软件阵列

    序言 软阵列是用软件实现的磁盘阵列. 准备工作 1. 更新系统 没啥,就他喵想用个最新的. apt update && apt upgrade 2. 安装mdadm 如果系统没有自带m ...

  5. Struts2_HelloWorld_6

    为 eclipse 在编写 xml配置文件时提供提示,需要加上dtd或xls的标签定义文件的路径,具体操作: 1.Window——Preferences——XML Catalog 2.添加 dtd 文 ...

  6. Js 数据类型 Number()转型函数

    alert(Number(true)); //转换为1,如果为false为0 alert(Number()); //25,数值型直接返回 alert(Number(null)); //0,空对象返回0 ...

  7. Codeforces Round #261 (Div. 2) - E (459E)

    题目连接:http://codeforces.com/contest/459/problem/E 题目大意:给定一张有向图,无自环无重边,每条边有一个边权,求最长严格上升路径长度.(1≤n,m≤3 * ...

  8. css3弹性盒子

    CSS3 弹性盒子(Flex Box) 弹性盒子是 CSS3 的一种新的布局模式. CSS3 弹性盒( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时 ...

  9. 数集合有多少个TOJ(2469)

    题目链接:http://acm.tju.edu.cn/toj/showp2469.html 感觉这个题目有点问题,算了不管他了,反正A了. 这里要注意的是求这个集合有多少种,那么就是要剔除重复数后,再 ...

  10. SQL按时间段统计(5分钟统计一次访问量为例,oracle统计)

    需求:统计当天的访问量,每五分钟采集一次 表结构中有日期字段,类型TIMESTAMP 如果,统计是采用每秒/分钟/小时/天/周/月/年,都非常容易实现,只要to_char日期字段然后group by分 ...