我的Python之旅第四天
一 名称空间、作用域、取值顺序
1 名称空间
当程序运行时,代码从上至下依次执行,它会将变量与值得关系存储在一个空间中,这个空间就叫做名称空间,也叫命名空间、全局名称空间。
当程序遇到函数时,他会将函数名存在内存中,对函数体漠不关心。
当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),函数外面访问不到临时空间的内容,随着函数的执行完毕,临时名称空间会释放掉,这个临时开辟的空间就叫名称空间,也叫局部名称空间。
Python中名称空间分三种:
- 内置名称空间
- 全局名称空间
- 局部名称空间
2 作用域
- 全局作用域
内置名称空间
全局名称空间
- 局部作用域
局部名称空间
3 加载顺序
内置名称空间à全局名称空间(当程序执行时)à局部名称空间(当函数调用时)
4 取值顺序:单向不可逆
局部名称空间(当函数调用时)à全局名称空间(当程序执行时)à内置名称空间
二 内置函数globals、locals
1返回值
(1)globals()
返回一个字典,字典里面的内容是全局作用域的内容。
(2) locals
返回一个字典,当前位置 的所有变量。
2 示例
name='ShiPotian'
age=''
sex='f'
def func1():
name2='XieYanke'
age=100
print('全局作用域为:',globals())
print('局部作用域为:',locals())
func1()
结果为: 全局作用域为: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000176723DC198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Python/python周末班/day04/globals,locals.py', '__cached__': None, 'name': 'ShiPotian', 'age': '', 'sex': 'f', 'func1': <function func1 at 0x0000017672033E18>} 局部作用域为: {'age': 100, 'name2': 'XieYanke'}
示例1
name='ShiPotian'
age=''
sex='f'
def func2():
name2='白自在'
age=10000
def func3():
name3='石中玉'
age3=''
print('全局作用域为:',globals())
print('局部作用域为:',locals()) func3()
func2()
结果为: 全局作用域为: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000297D51CC198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Python/python周末班/day04/globals,locals.py', '__cached__': None, 'name': 'ShiPotian', 'age': '', 'sex': 'f', 'func2': <function func2 at 0x00000297D4E23E18>} 局部作用域为: {'age3': '', 'name3': '石中玉'}
示例2
三 global与nonlocal
1 global
(1)引用并改变一个全局变量
count=1
def func1():
global count
count= count+1
count=count+100
print(count)
func1() 结果为:102
(2)在局部作用域声明一个全局变量
def func2():
global name
name='谢烟客'
print('局部定义的全局变量:',name)
func2()
print('全局引用局部定义的全局变量:',name)
结果为: 局部定义的全局变量: 谢烟客
全局引用局部定义的全局变量: 谢烟客
2 nonlocal
(1)不能操作全局变量,从那层引用的变量,就从那层开始全部改变
count = 100
def func3():
count = 1
def inner1():
nonlocal count
count = count + 3
print('开始引用层的变量值:',count)
def inner2():
pass
inner1()
print('第一层函数的变量值:',count
func3()
print("全局作用域的变量值:",count)
结果为: 开始引用层的变量值: 4
第一层函数的变量值: 4
全局作用域的变量值: 100
nonlocal
(2)取值
引用而不是改变,想要改变上层空间的变量,要用到global、nonlocal
3 特别注意
(1)对于可变的数据类型 list dict set 不用global nonlocal
(2)如果默认参数是一个可变的数据类型,那么他在内存中永远是一个
示例
def extendList(val,list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print('list1=%s'%list1)
print('list2=%s'%list2)
print('list3=%s'%list3)
结果为: list1=[10, 'a']
list2=[123]
list3=[10, 'a']
示例
四 函数名的应用
1 打印函数名
def func1():
print(111)
print(func1)
结果为:<function func1 at 0x000001B578743E18>
输出结果为函数名在内存中的地址
2 函数名可以作为容器类数据的元素
def func1():
print(111)
def func2():
print(222)
def func3():
print(333)
l1=[func1,func2,func3]
for i in l1:
i()
结果为: 111
222
333
3 函数名作为函数的参数
def func1():
print("This is func1")
def func2(x):
print("This is func2")
func2(func1)
结果为:This is func2
4 函数名可以作为函数的返回值
def func1():
print("This is func1")
def func2(x):
print("This is func2")
return x
ret=func2(func1) 此行相当于 ret=func1
print(ret)
结果为: This is func2
<function func1 at 0x0000020417DD3E18>
五 闭包函数
1 闭包的定义
内层函数对外层函数非全局变量的引用,就叫做闭包
2 基本的闭包函数示例
def wrapper():
name='qiaofeng'
def inner():
print(name)
inner()
wrapper()
结果为:qiaofeng
3 检验是否为闭包
通过函数名.__closure__检验,如果结果为空则不是闭包函数
def wrapper():
name='qiaofeng'
def inner():
print(name)
inner()
print('测试__closure__的内存地址为:\n',inner.__closure__)
wrapper() 结果为:
qiaofeng
测试__closure__的内存地址为:
(<cell at 0x00000130C3607468: str object at 0x00000130C369D730>,)
检查是否为闭包函数
4 用处
如果Python解释器遇到了闭包,他有一个机制,就是这个闭包函数不会随着函数的结束而释放
六 装饰器
需求:测试一个函数的执行效率
定义两个待测的函数
def func1():
time.sleep(0.5)
print('测试函数func1的执行时间...')
def func2():
time.sleep(0.3)
print('测试函数func2的执行时间...')
#version:0
import time
def func1():
time.sleep(0.5)
print('测试此函数的执行时间...')
start_time=time.time()
func1()
end_time=time.time()
print("此函数的执行时间为:%s" %(end_time-start_time))
结果为: 测试函数func1的执行时间...
此函数的执行时间为:0.5000154972076416
最初版本
1 需求:要求封装到一个函数中
import time
def timmer():
def func1():
time.sleep(0.5)
print('测试函数func1的执行时间...')
start_time=time.time()
func1()
end_time=time.time()
print("此函数的执行时间为:%s" %(end_time-start_time))
timmer()
执行结果为: 测试函数func1的执行时间...
此函数的执行时间为:0.5008091926574707
version1
2 需求:被测试函数当参数传入,可以测试多个函数的执行效率
def timmer(f):
start_time=time.time()
f()
end_time=time.time()
print("此函数的执行时间为:%s" %(end_time-start_time))
timmer(func1)
timmer(func2)
结果为:
测试函数func1的执行时间...
此函数的执行时间为:0.5004558563232422
测试函数func2的执行时间...
此函数的执行时间为:0.3000974655151367
version2
3 需求:测试函数执行效率的同时,不要改变原函数的调用方式
#version:3
def timmer(f):
start_time=time.time()
f()
end_time=time.time()
print("此函数的执行时间为:%s" %(end_time-start_time)) f1=func1
func1=timmer #这步相当于把timmer这个函数名赋值给func1
func1(f1) ##这步相当于timmer(func1)
结果为: 测试函数func1的执行时间...
此函数的执行时间为:0.5001800060272217
4 最简单的装饰器
虽然version3大体上满足了我的需求,但是增加两行代码,而且多了个参数,感觉不够好,需要继续改,尽量不要添加其它代码,而且做到调用时一模一样
#version:4 def timmer(f):
start_time=time.time()
f()
end_time=time.time()
print("此函数的执行时间为:%s" %(end_time-start_time))
func1=timmer(func1)
结果为: 测试函数func1的执行时间...
此函数的执行时间为:0.5006768703460693
最简单装饰器
5 语法糖@
版本4每次测试一个函数的执行效率是,都需要加一行func=timmer(func1),麻烦,于是Python提出了一个语法糖 @。
def timmer(f):
def inner():
start_time=time.time()
f()
end_time=time.time()
print("此函数的执行时间为:%s" %(end_time-start_time))
return inner
@timmer
def func1():
time.sleep(0.5)
print('测试函数func1的执行时间...')
func1()
结果为:
测试函数func1的执行时间...
此函数的执行时间为:0.5005886554718018
语法糖@
6 有参装饰器
被装饰的函数肯定是要有参数的,version5不能满足,必须改造成一个有参装饰器
def timmer(f):
def inner(*args,**kwargs):
start_time=time.time()
f(*args,**kwargs)
end_time=time.time()
print("此函数的执行时间为:%s" % (end_time - start_time))
return inner
@timmer
def func1(a,b,name,sex='male'):
time.sleep(0.5)
print(a,b,name,sex)
print('测试函数func1的执行时间...') func1(1,2,name='daozhu')
结果为:
1 2 daozhu male
测试函数func1的执行时间...
此函数的执行时间为:0.5006396770477295
有参装饰器
7 带返回值的装饰器
被装饰的函数肯定是要有返回值的,解决这个问题。
def timmer(f):
def inner(*args,**kwargs):
start_time=time.time()
ret=f(*args,**kwargs)
end_time=time.time()
print("此函数的执行时间为:%s" % (end_time - start_time))
return ret
return inner
@timmer
def func3(a,b,name,sex='male'):
time.sleep(0.4)
print(a,b,name,sex)
print('测试函数func2的执行时间...')
func3(1,2,sex='fmale',name='alex')
结果为:
1 2 alex fmale
测试函数func2的执行时间...
此函数的执行时间为:0.4004359245300293
有返回值的装饰器
8 完整的装饰器示例
def timmer(f):
def inner(*args,**kwargs):
start_time = time.time()
ret = f(*args,**kwargs)
end_time = time.time()
print('此函数的执行效率%s' % (end_time - start_time))
return ret
return inner @timmer
def func1():
………
完整装饰器示例
装饰器的本质就是闭包函数
我的Python之旅第四天的更多相关文章
- Python之旅.第四章.模块与包.总结(未完待遇)
一.模块 模块: 一系列功能的集合体,在python中一个py文件就是一个模块,模块名就是py文件的文件名: 模块的好处: 1.减少重复的代码 2.拿来主义 定义模块: 就是创建一个py文件: 使用模 ...
- Python之旅.第四章.模块与包 4.02
一.模块的使用之import 1 什么是模块?模块就一系统功能的集合体,在python中,一个py文件就是一个模块,比如module.py,其中模块名module2 使用模块2.1 import 导入 ...
- Python之旅第四天(列表、元祖、字典和习题)
第四天,感觉时间还是过得很快,今天内容确实有点多,关于list的方法实在是太多了,元组tuple感觉有点鸡肋,可能得到后面才知道他的作用吧,然后是字典,看了很多关于字典的介绍,但是这货到底是干啥用的一 ...
- python学习心得第四章
python 学习心得第四章 1.lambda表达式 1:什么是lambda表达式 为了简化简单函数的代码,选择使用lambda表达式 上面两个函数的表达式虽然不一样,但是本质是一样的,并且lamb ...
- webpack入坑之旅(四)扬帆起航
这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...
- 机器学习算法与Python实践之(四)支持向量机(SVM)实现
机器学习算法与Python实践之(四)支持向量机(SVM)实现 机器学习算法与Python实践之(四)支持向量机(SVM)实现 zouxy09@qq.com http://blog.csdn.net/ ...
- Selenium WebDriver + Grid2 + RSpec之旅(四) ----通过RSpec编写测试用例
Selenium WebDriver + Grid2 + RSpec之旅(四) ----通过RSpec编写测试用例 自动化测试和手工测试一样,是要有测试用例,有检查点和测试结果的,接下来我们通过RSp ...
- 【Python之旅】第六篇(七):开发简易主机批量管理工具
[Python之旅]第六篇(七):开发简易主机批量管理工具 python 软件开发 Paramiko模块 批量主机管理 摘要: 通过前面对Paramiko模块的学习与使用,以及Python中多线程与多 ...
- Python爬虫学习:四、headers和data的获取
之前在学习爬虫时,偶尔会遇到一些问题是有些网站需要登录后才能爬取内容,有的网站会识别是否是由浏览器发出的请求. 一.headers的获取 就以博客园的首页为例:http://www.cnblogs.c ...
随机推荐
- php namespace与use
实验代码 ~/aa.php ~/bb.php 1.命名空间与文件加载的关系 本人在命名空间与文件加载上一直有一个误区,用了命名空间文件不用加载了? 实验1:去掉requre语句 可以看到就算使用命名空 ...
- go socket
https://tonybai.com/2015/11/17/tcp-programming-in-golang/ Golang的主要 设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端 程 ...
- 在MinGW下编译ffmpeg
因为需要使用ffmpeg的相关库和执行文件,所以需要编译最新的ffmpeg代码.为了能在编译成Windows native执行程序(需要在.net中调用该执行程序),这里我们使用MinGW. 1,安装 ...
- JavaScript 中的undefined and null 学习
JavaScript 中的undefined and null learn record from the definitive guide to html5 JavaScript 中有两个特殊值:u ...
- es6(五):class关键字(extends,super,static)
ES5中,生成对象通过构造函数: function A(name,age){ this.name=name; this.age=age } // 在A的prototype属性上定义一个test方法,即 ...
- Java经验杂谈(2.对Java多态的理解)
多态是面向对象的重要特性之一,我试着用最简单的方式解释Java多态: 要正确理解多态,我们需要明确如下概念:・定义类型和实际类型・重载和重写・编译和运行 其中实际类型为new关键字后面的类型. 重载发 ...
- Hbase出现ERROR: Can't get master address from ZooKeeper; znode data == null解决办法
问题描述如下: hbase(main)::> list TABLE ERROR: Can't get master address from ZooKeeper; znode data == n ...
- 多层嵌套的json数据
很多时候我们见到的json数据都是多层嵌套的,就像下面这般: {"name":"桔子桑", "sex":"男", , & ...
- php坏境安装Xdebug详情步骤
原创,转载请注明出处! Xdebug是一个开放源代码的PHP程序调试器(即一个Debug工具),可以用来跟踪,调试和分析PHP程序的运行状况,可以说是程序员必备的一个工具之一.好了,进入正题: 1.下 ...
- docker学习笔记(一)—— ubuntu16.04下安装docker
docker学习笔记(一)—— ubuntu16.04下安装docker 原创 2018年03月01日 14:53:00 标签: docker / ubuntu 1682 本文开发环境为Ubuntu ...