代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间,在函数的运行中开辟的临时的空间叫做局部命名空间

命名空间和作用域

  命名空间的本质:存放名字与值的绑定关系

 >>> import this
The Zen of Python, by Tim Peters Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

在python之禅中提到过:命名空间是一种绝妙的理念,让我们尽情的使用发挥吧!

命名空间一共分为三种:

  全局命名空间

  局部命名空间

  内置命名空间

*内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。

三种命名空间之间的加载与取值顺序:

加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

取值:

  在局部调用:局部命名空间->全局命名空间->内置命名空间

  在局部使用变量取值情况

 x = 1
def f(x):
print(x) print(10)

  在全局调用:全局命名空间->内置命名空间

  在全局引用变量x

 x = 1
def f(x):
print(x) f(10)
print(x)

在全局引用内置max 

 print(max)

作用域

  作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

  全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

  局部作用域:局部名称空间,只能在局部范围生效

  globals和locals方法

  在全局引用globals和locals

 print(globals())
print(locals()) C:\Users\panhw\AppData\Local\Programs\Python\Python36\python.exe C:/Users/panhw/Desktop/学习文档/python/day15.py
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000023BB77CA4A8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/panhw/Desktop/学习文档/python/day15.py', '__cached__': None, 'sys': <module 'sys' (built-in)>, 'li': [2, 3, 5, 10, 15, 16, 18, 22, 26, 30, 32, 35, 41, 42, 43, 55, 56, 66, 67, 69, 72, 76, 82, 83, 88], 'count': 1}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000023BB77CA4A8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/panhw/Desktop/学习文档/python/day15.py', '__cached__': None, 'sys': <module 'sys' (built-in)>, 'li': [2, 3, 5, 10, 15, 16, 18, 22, 26, 30, 32, 35, 41, 42, 43, 55, 56, 66, 67, 69, 72, 76, 82, 83, 88], 'count': 1}

  在局部引用globals和locals

 def func():
a = 12
b = 20
print(locals())
print(globals()) func() C:\Users\panhw\AppData\Local\Programs\Python\Python36\python.exe C:/Users/panhw/Desktop/学习文档/python/day15.py
{'b': 20, 'a': 12}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001FEE5D2A4A8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/panhw/Desktop/学习文档/python/day15.py', '__cached__': None, 'sys': <module 'sys' (built-in)>, 'li': [2, 3, 5, 10, 15, 16, 18, 22, 26, 30, 32, 35, 41, 42, 43, 55, 56, 66, 67, 69, 72, 76, 82, 83, 88], 'count': 1, 'func': <function func at 0x000001FEE4123E18>}

  global 关键字

 a = 10
def func():
global a
a = 20 print(a)
func()
print(a)

函数的嵌套和作用域链

  函数的嵌套调用

 def max2(x,y):
m = x if x>y else y
return m def max4(a,b,c,d):
res1 = max2(a,b)
res2 = max2(res1,c)
res3 = max2(res2,d)
return res3 # max4(23,-7,31,11)

  函数的嵌套定义

 def f1():
print("in f1")
def f2():
print("in f2") f2()
f1()

嵌套定义(一)

嵌套定义(二)

  函数的作用域链

 def f1():
a = 1
def f2():
print(a)
f2() f1()

作用域链(一)

 def f1():
a = 1
def f2():
def f3():
print(a)
f3()
f2() f1()

作用域链(二)

 def f1():
a = 1
def f2():
a = 2
f2()
print('a in f1 : ',a) f1()

作用域链(三)

  nonlcoal 关键字

    1.外部必须有这个变量
    2.在内部函数声明nonlocal变量之前不能再出现同名变量
    3.内部修改这个变量如果想在外部有这个变量的第一层函数中生效

 def f1():
a = 1
def f2():
nonlocal a
a = 2
f2()
print('a in f1 : ',a) f1()

函数名的本质

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

  1.可以被引用

 def func():
print('in func') f = func
print(f)

函数引用

  2.可以被当作容器类型的元素

 def f1():
print('f1') def f2():
print('f2') def f3():
print('f3') l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
#调用
l[0]()
d['f2']()

当做容器

  3.可以当作函数的参数和返回值

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

闭包

  闭包函数:

    内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
    函数内部定义的函数称为内部函数

  在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

 def func(name):
def inner_func(age):
print 'name:', name, 'age:', age
return inner_func bb = func('the5fire')
bb(26) # >>> name: the5fire age: 26

  闭包函数最常用的用法

 def func():
name = 'eva'
def inner():
print(name)
return inner f = func()
f()

  判断闭包函数的方法__closure__

 #输出的__closure__有cell元素 :是闭包函数
def func():
name = 'eva'
def inner():
print(name)
print(inner.__closure__)
return inner f = func()
f() #输出的__closure__为None :不是闭包函数
name = 'egon'
def func2():
def inner():
print(name)
print(inner.__closure__)
return inner f2 = func2()
f2()

  闭包嵌套

 def wrapper():
money = 1000
def func():
name = 'eva'
def inner():
print(name,money)
return inner
return func f = wrapper()
i = f()
i()

  闭包函数获取网络应用

 from urllib.request import urlopen

 def index():
url = "http://www.xiaohua100.cn/index.html"
def get():
return urlopen(url).read()
return get xiaohua = index()
content = xiaohua()
print(content)

命名空间:

  一共有三种命名空间从大范围到小范围的顺序:内置命名空间、全局命名空间、局部命名空间

作用域(包括函数的作用域链):

小范围的可以用大范围的
但是大范围的不能用小范围的
范围从大到小(图)

在小范围内,如果要用一个变量,是当前这个小范围有的,就用自己的
如果在小范围内没有,就用上一级的,上一级没有就用上上一级的,以此类推。
如果都没有,报错

函数的嵌套:

  嵌套调用

  嵌套定义:定义在内部的函数无法直接在全局被调用

函数名的本质:

  就是一个变量,保存了函数所在的内存地址

闭包:

  内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数

2. 为什么使用闭包

基于上面的介绍,不知道读者有没有感觉这个东西和类有点相似,相似点在于他们都提供了对数据的封装。不同的是闭包本身就是个方法。和类一样,我们在编程时经常会把通用的东西抽象成类,(当然,还有对现实世界——业务的建模),以复用通用的功能。闭包也是一样,当我们需要函数粒度的抽象时,闭包就是一个很好的选择。

在这点上闭包可以被理解为一个只读的对象,你可以给他传递一个属性,但它只能提供给你一个执行的接口。因此在程序中我们经常需要这样的一个函数对象——闭包,来帮我们完成一个通用的功能,比如后面会提到的——装饰器。

3. 使用闭包

第一种场景 ,在python中很重要也很常见的一个使用场景就是装饰器,Python为装饰器提供了一个很友好的“语法糖”——@,让我们可以很方便的使用装饰器,装饰的原理不做过多阐述,简言之你在一个函数func上加上@decorator_func, 就相当于decorator_func(func):

 def decorator_func(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper @decorator_func
def func(name):
print 'my name is', name # 等价于
decorator_func(func)

13 Python 函数进阶的更多相关文章

  1. python函数进阶(函数参数、返回值、递归函数)

    函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形 ...

  2. 第六篇:Python函数进阶篇

    在了解完了 Python函数基础篇之后,本篇的存在其实是为了整合知识,由于该篇的知识是否杂乱,故大家可以通过点开点连接直接进入其详细介绍,该篇主要大致的介绍一下几个知识点:  一.Python的迭代器 ...

  3. python 函数进阶与闭包

    函数的命名空间和作用域 引言 现在有个问题,函数里面的变量,在函数外面能直接引用么? def func1(): m = 1 print(m) print(m) #这行报的错 报错了: NameErro ...

  4. python函数进阶

    知识内容: 1.函数即变量 2.嵌套函数 3.lambda表达式与匿名函数 4.递归函数 5.函数式编程简介 6.高阶函数与闭包 一.函数即变量 1.变量的本质 声明一个变量,在python里本质上讲 ...

  5. python -- 函数进阶

    一.函数参数-动态传参       1.形参:         *   在形参位置, 表示此参数为不定参数,接受的是位置参数            并且接收到的位置参数的动态传参都是元组 def fu ...

  6. 万恶之源 - Python函数进阶

    函数参数-动态参数 之前我们说过传参,如果我们在传参数的时候不很清楚有哪些的时候,或者说给一个函数传了很多参数,我们就要写很多,很麻烦怎么办呢,我们可以考虑使用动态参数 形参的第三种:动态参数 动态参 ...

  7. Python 函数进阶(filter/map/json/zip)

    一.函数即变量 def say(name): print(name)ybq = say #可以被赋值给其他变量ybq('Amily') #调用函数 函数名:say 函数体:第1-2行 返回值:retu ...

  8. Python—函数进阶篇

    lambda表达式(匿名函数表达式) 作用:创建一个匿名函数对象.同def类似,但不提供函数名. 语法:lambda [形参1,形参2,...] : 表达式 语法说明 lambda 只是一个表达式,它 ...

  9. Python函数进阶:闭包、装饰器、生成器、协程

    返回目录 本篇索引 (1)闭包 (2)装饰器 (3)生成器 (4)协程 (1)闭包 闭包(closure)是很多现代编程语言都有的特点,像C++.Java.JavaScript等都实现或部分实现了闭包 ...

随机推荐

  1. Elasticsearch5.X IN Windows 10 系列文章(1)

    系统类型:windows10  64位家庭版 ElasticSearch版本: 5.5.1 (最新稳定版为5.5.2),由于用到IK中文分词插件,最新版本没有5.5.2 ,所以使用5.5.1 日期:2 ...

  2. 好文章收藏--五分钟理解一致性哈希算法(consistent hashing)

    一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简 单哈 ...

  3. volatile的含义及使用场景

    volatile保证线程间的数据是可见的(共享的),但不保证数据同步 volatile相当于synchronized的弱实现,也就是说volatile实现了类似synchronized的语义,却又没有 ...

  4. 百度地图SnapshotReadyCallback截屏

    今天碰到了地图截图的功能,不太会,查查资料知道怎么弄了,跟大家分享一下 直接上代码,弄了一个方法,将截取的图片上传至服务器,返回给我们图片路径 //获取地图截图 private void getscr ...

  5. js校验密码强度

    网上转载的一段代码,留着以后用, js文件: //判断输入密码的类型 function CharMode(iN){ if (iN>=48 && iN <=57) //数字 ...

  6. 感知器(Perception)

    感知器是一种早期的神经网络模型,由美国学者F.Rosenblatt于1957年提出.感知器中第一次引入了学习的概念,使人脑所具备的学习功能在基于符号处理的数学到了一定程度模拟,所以引起了广泛的关注. ...

  7. Basis 基础

    [转自 http://www.cnblogs.com/elegantok/archive/2008/11/03/1325163.html] 1 Basis1. Unix操作 更改口令 passwd e ...

  8. Linux系统BTC挖矿傻瓜教程

    [Linux系统BTC/比特币矿池挖矿方案一]cgminer矿池挖矿程序(Linux系统 比特币(BTC) 矿池挖矿/采矿/造币)cgminer矿池挖矿程序[查看这里有没有最新版]http://ck. ...

  9. 【LeetCode】 数相加组合 Combination Sum

    描述 Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), ...

  10. c++ 之重要性

    c++的功能比c语言大的多,c语言偏最底层,且程序短小,而对于一个大的系统,用c++,因为它具备了c语言的优点. 很多学嵌入式的觉得学了c语言之后,就不用学c++了,会认为c++很简单,然而,c++并 ...