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

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

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

x=1      #全局赋值变量
def foo():
global x    #函数内部全局声明变量x
x=1111111    #函数内部修改全局变量x
print(x)
foo()
print(x)

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

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

def f1():
# x=2
def f2():
x=3
def f3():
nonlocal x
x=1111
# print('f3',x)
f3()
print('f2',x)
f2()
# print('f1',x)
f1()

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

闭包函数

闭包函数定义:

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

定义闭包函数:

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

闭包函数指的是内部函数

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

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

示例:

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

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

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

装饰器基础

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

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

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

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

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

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

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

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

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

import time
import random def index_new(func):
def timmer():
start_time=time.time()
func()
stop_time=time.time()
print('time:%s' %(stop_time-start_time))
return timmer def index():    #源代码并不改变
time.sleep(random.randrange(1,5))
print('hello world') index=index_new(index)
index() 输出结果:
hello world
time:3.000032663345337

示例三:装饰器调用语法

def index_new(func):
def timmer():
start_time=time.time()
func()
stop_time=time.time()
print('time:%s' %(stop_time-start_time))
return timmer
#使用@符号进行调用
@index_new #index=index_new(index)
def index():
time.sleep(random.randrange(1,5))
print('hello world') index()

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

import time
import random
#装饰器1:计时模块
def timmer(func):
def wrapper():
start_time = time.time()
func()
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
return wrapper
#装饰器2:认证模块
def auth(func):
def deco():
name=input('name: ')
password=input('password: ')
if name == 'egon' and password == '123':
print('login successful')
func() #wrapper()
else:
print('login err')
return deco #被装饰函数
@auth #index=auth(wrapper) #index=deco #index=auth(wrapper) #index=deco
@timmer #index=timmer(index) #index=wrapper
def index():
# time.sleep(random.randrange(1,5))
time.sleep(3)
print('welecome to index page') #并没有调用任何装饰器
def home():
time.sleep(random.randrange(1,3))
print('welecome to HOME page') index() #deco()
home()

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

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

import time
import random
#装饰器
def timmer(func):
def wrapper(*args,**kwargs):  #*args和**kwargs能够接收任意的参数,并且可以不存在,接收后原封不动传入到func调用的函数
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
#被装饰函数 @timmer
def index():
time.sleep(random.randrange(1,5))
print('welecome to index page')
@timmer
def home(name):
time.sleep(random.randrange(1,3))
print('welecome to %s HOME page' %name)
return 123123123123123123123123123123123123123123 res1=index()
print('index return %s' %res1)
res2=home('egon') #wraper()
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. ECMAScript Regex

    Everything has its own regulation by defining its grammar. ECMAScript regular expressions pattern sy ...

  2. Java1.7新特性

    1.switch语句支持字符串变量 public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) { String typeOf ...

  3. 给网站添加图标: Font Awesome

    先贴上各种图标的网址:https://fontawesome.com/?from=io 1.打开网址,我们可以看到: 像我这种英语不好的,直接用谷歌浏览器进行翻译中文好了,自己还是有点B数的····· ...

  4. Html5 web本地存储

    Web Storage是HTML5引入的一个非常重要的功能,可以在客户端本地存储数据,类似HTML4的cookie,但可实现功能要比cookie强大的多,cookie大小被限制在4KB,Web Sto ...

  5. POJ-2151 Check the difficulty of problems---概率DP好题

    题目链接: https://vjudge.net/problem/POJ-2151 题目大意: ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率 问 每队至少解出一题且冠军队至少解出N ...

  6. Android(java)学习笔记62:android.intent.action.MAIN 与 android.intent.category.LAUNCHER 理解

    1. 先看看网路上的说法: android.intent.action.MAIN 决定应用程序最先启动的 Activity android.intent.category.LAUNCHER 决定应用程 ...

  7. 在线文本编辑器cheditor应用实例

    CKEditor 即 FCKEDITOR . FCKeditor是眼下最棒的可见就可以得网页编辑器之中的一个,它採用JavaScript编写.具备功能强大.配置easy.跨浏览器.支持多种编程语言.开 ...

  8. 贪心,POJ(2709)

    题目链接:http://poj.org/problem?id=2709 解题报告: #include <stdio.h> #include <algorithm> #inclu ...

  9. Codeforces Round #347 (Div.2)_A. Complicated GCD

    题目链接:http://codeforces.com/contest/664/problem/A A. Complicated GCD time limit per test 1 second mem ...

  10. Oracle数据库几种启动方式及查询当前状态

    Oracle数据库几种启动方式 1.startup nomount: 非安装启动,这种方式下启动可执行:重建控制文件.重建数据库,读取init.ora文件,启动instance,即启动SGA和后台进程 ...