Python进阶之路(二),命名空间namespace

2019-07-08  本文已影响0人  EchoPython

引言

:在通常认知中,变量是一段具有特定格式的内存,变量名是内存别名,因为在编码阶段,无法确定内存的具体位置,故事用名称层符号代替.
注意:变量名和指针不同

接下来,静态编译和动态解释性语言对于变量名的处理方式完全不同,静态编译器或连接器会以固定地址,或者直接间接寻址执行代替变量名,也就是说变量名不参与执行过程,可以被剔除 ;但是在解释性语言中,名字和对象通常是两个运行期试题,名字不但有自己的类型,还需要分配内存,并且介入执行过程,甚至可以说,名字才是动态模型的基础.(比如 C#,JAVA,Python,PhP都是动态语言).

如果将内存寻址比喻成为顾客按照编号寻找服务柜台,那么名字就是一个接待员,任何时候,顾客都只能够通过他间接与目标服务互动.从表面看这好像是高级会员才有的东西,但是实际上增加了中间环节和额外的开销,于性能不利,但是好处是,接待员和服务之间拥有更多的调整空间,可以用来增加代理和安全机制,甚至为缓存管理提供机会,后续会更新出有关元变成的内容.

当然名字必须和目标对象关联起来才有意义.

In [1]: x                                                                                                                                                                                    
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-6fcf9dfbd479> in <module>
----> 1 x

NameError: name 'x' is not defined

In [2]:  

最直接的关联操作就是赋值,然后对名字的引用都被解释为对目标对象进行操作

In [2]: x = 100                                                                                                                                                                              

In [3]: x                                                                                                                                                                                    
Out[3]: 100

In [4]: x +=2                                                                                                                                                                                

In [5]: x                                                                                                                                                                                    
Out[5]: 102

In [6]:  

赋值步骤,

  1. 将准备好右值目标对象(100)
  2. 准备好名字 (x)
  3. 在名字空间里为两者建立关联(namespace {x:100})

即便如此,名字与目标对象之间也仅仅是引用关联,名字只负责找人,但对于此人一无所知.只有在运行期间才知道名字引用的目标类型,所以说Python是一种动态语法/

name have no type,but objects do


名字空间

名字空间(namespace) 是上下文环境中专门用来储存名字和目标引用关联的容器,如图所示


在这里插入图片描述

对于Python而言,每个模块(源码文件)都有一个全局名字空间,而根据代码作用域,又有当前名字或者本地名字空间一说.如果在模块级别执行,那么当前名字空间和全局名字空间相同,但是在函数中,当前名字就是专值函数作用域.


名字空间默认使用字典(dict) 数据结构,有多个键值(key/value) 组成.
内置函数globals和locals分别返回全局名字空间,和本地名字空间字典.


In [6]: x = 100                                                                                                                                                                              

In [7]: id(globals())                                                                                                                                                                        
Out[7]: 140077279009480

In [8]: id(locals())                                                                                                                                                                         
Out[8]: 140077279009480

In [9]: globals()                                                                                                                                                                            
Out[9]: 
{'In': ['',
  'x',
  'x = 100',
  ........


In [11]: def test(): 
    ...:     x = 'hello world' 
    ...:     print(locals())       # 指向本地命名空间
    ...:     print("locals:",id(locals())) 
    ...:     print("globals",id(globals()))  # 指向全局命名空间
    ...:    
    ...:                                                                                                                                                                                     

In [12]: test()        # 在函数作用域调用                                                                                                                                                              
{'x': 'hello world'}   # 此时,locals 输入函数名字空间
locals: 140077240118024 # locals != globals
globals 140077279009480 


可见,globals 总是固定指向模块名字空间,而locals 则指向当前作用域环境

在这里插入图片描述

在初步了解后,我们甚至可以直接修改名字空间建立关联医用,这与传统变量定义方式有何不同.


In [17]: globals()["hello"] = "hello,world"                                                                                                                                                  

In [18]: globals()["number"] = 123455                                                                                                                                                        

In [19]: hello                                                                                                                                                                               
Out[19]: 'hello,world'

In [20]: number                                                                                                                                                                              
Out[20]: 123455


并非所有时候都能直接操作命名空间,函数执行使用缓存机制,可以直接修改本地名字空间未必有效,在正常编码时,应该尽可能避免直接修改名字空间


在名字空间的字典中,名字只是简单字符串主键,其自身数据结构里面没有任何目标对象信息,通过名字访问目标对象,无非是以名字为主键去字典中读取目标对象指针引用.也正因为如此,名字可以重新关联另外一个对象,完全不在于其类型是否与前任相同.

In [21]: x = 100                                                                                                                                                                             

In [22]: x                                                                                                                                                                                   
Out[22]: 100

In [23]: id(x)                                                                                                                                                                               
Out[23]: 10922592

In [24]: globals()                                                                                                                                                                           
Out[24]: 
{'In': ['',
  'x',
  'x = 100',
  ......


In [25]: x = "abc"                  #重新关联一个对象                                                                                                                                                         

In [26]: x                                                                                                                                                                                   
Out[26]: 'abc'

In [27]: id(x)                       # 通过输出的id可以看出关联新对象,并非修改原对象内容                                                                                                                                             
Out[27]: 140077358909568

In [28]: globals()                   # 名字空间的引用变更                                                                                                                                                        
Out[28]: 
{'In': ['',
  'x',
  'x = "abc",



赋值操作仅仅是让名字在命名空间中重新关联,并非是修改原对象


在这里插入图片描述

和一个名字只能够引用一个对象不同,单个对象可以拥有多个名字,无论是在相同或者不相同的名字空间中


一个人在公司中,他可以是老王,王大叔,王哥哥等..这时这个人在办公室中就拥有了多个名字,出了办公司,在全公司,(另外一个命名空间)范围中,他还可以有王处长,王老板等其他名字.

命名规则

名字应该有实际含义,并且阅读和理解的字母或者单词组合

In [3]: x = "abc"                                                                                                                                                                            

In [4]: X = "1"                                                                                                                                                                              

In [5]: X is x                                                                                                                                                                               
Out[5]: False

In [6]:      

为了统一命名风格


尽管Python3 中可以使用汉字作为变量名,但是并不推荐


In [7]: import keyword                                                                                                                                                                       

In [8]: keyword.kwlist      # 打印出Python3中的保留关键词                                                                                                                                                                 
Out[8]: 
['False',
 'None',
 'True',
 'and',
 'as',
 'assert',
 'break',
 'class',
 'continue',
 'def',
 'del',
 'elif',
 'else',
 'except',
 'finally',
 'for',
 'from',
 'global',
 'if',
 'import',
 'in',
 'is',
 'lambda',
 'nonlocal',
 'not',
 'or',
 'pass',
 'raise',
 'return',
 'try',
 'while',
 'with',
 'yield']



注意 python3中print 不再是关键字,是一个函数,但是在python2中仍旧是保留关键字

上一篇下一篇

猜你喜欢

热点阅读