python基础入门----命名空间和变量作用域

原文链接:https://www.programiz.com/python-programming/namespace

Table of Contents


表格内容

  • python里什么是名字?
  • 在python里什么是命名空间
  • 变量范围
  • 范围和命名空间的例子

What is Name in Python?

If you have ever read 'The Zen of Python' (type "import this" in Python interpreter), the last line states, Namespaces are one honking great idea -- let's do more of those! So what are these mysterious namespaces? Let us first look at what name is.

Name (also called identifier) is simply a name given to objects. Everything in Python is anobject. Name is a way to access the underlying object.

什么是名字

如果你曾经读过'The Zen of Python'(在python解释器输入"import this").最后一行的声明,命名空间是一个很棒的想法----让我们做更多这样的事吧!因此什么是神秘的命名空间?让我们首先看看什么事名字。

名字(也称为身份特征)是对象简单的一个名字。在python中,任何事物都是一个对象。名字是一个访问底层你给的方法。


For example, when we do the assignment a = 2, here 2 is an object stored in memory and a is the name we associate it with. We can get the address (in RAM) of some object through the built-in functionid(). Let's check it.

# Note: You may get different value of id

a = 2
# Output: id(2)= 10919424
print('id(2) =', id(2))

# Output: id(a) = 10919424
print('id(a) =', id(a))

例如:当我们做赋值a = 2,这里的2是一个存储对象在内存,a是一个名字,我们可以联系到它。我们可以通过内建函数id

()获取到某些对象的地址(在内存),让我们检查它。

>>> a = 2
>>> print('id(2) =',id(2))
id(2) = 10919360
>>> print('id(a) =',id(a))
id(a) = 10919360

Here, both refer to the same object. Let's make things a little more interesting.

# Note: You may get different value of id

a = 2

# Output: id(a) = 10919424
print('id(a) =', id(a))

a = a+1

# Output: id(a) = 10919456
print('id(a) =', id(a))

# Output: id(3) = 10919456
print('id(3) =', id(3))

b = 2

# Output: id(2)= 10919424
print('id(2) =', id(2))

这里,两个引用到相同的地址。让我们做一些更有意思的事吧。

>>> a = 2
>>> print('id(a) = ',id(a))
id(a) =  10919360
>>> a = a+1
>>> print('id(a) = ',id(a))
id(a) =  10919392
>>> print('id(3) = ',id(3))
id(3) =  10919392
>>> b = 2
>>> print('id(2) =',id(2))
id(2) = 10919360

What is happening in the above sequence of steps? A diagram will help us explain this.

Memory diagram of a variable

Initially, an object 2 is created and the name a is associated with it, when we do a = a+1, a new object 3 is created and now a associates with this object.

Note that id(a) and id(3) have same values.

Furthermore, when we do b = 2, the new name b gets associated with the previous object2.

This is efficient as Python doesn't have to create a new duplicate object. This dynamic nature of name binding makes Python powerful; a name could refer to any type of object.

>>> a = 5
>>> a = 'Hello World!'
>>> a = [1,2,3]

All these are valid and a will refer to three different types of object at different instances.Functions are objects too, so a name can refer to them as well.

def printHello():
    print("Hello")     
a = printHello()

# Output: Hello
a

Our same name a can refer to a function and we can call the function through it, pretty neat.

上面的步骤序列发生了什么?一张图可以帮我们解释到这点。

Memory diagram of a variable

最初,一个对象2被创建,这个名字能联系到它,当我们做a = a+1,一个新的对象3被创建,现在联系到它。

注意,这个id(a)和id(3)有相同的值。

此外,当我们做b = 2,这新的名字b获取到联系之前的对象2.

这个对于python不能创建新的重复对象是非常有效率的。这个动态名字绑定的特征使python很强大;一个名字可以索引到任何一个类型的对象。 

>>> a = 5
>>> a = 'Hello World!'
>>> a = [1,2,3]

这些都是有效的,a将会引用不同类型的对象在不同实例中。函数也是对象,所以名字也可以引用到他们。

def printHello():
    print("hello")
a = printHello()

a

我们相同的a可以引用到a函数,我们可以通过这个函数调用它,非常简洁。


What is a Namespace in Python?

So now that we understand what names are, we can move on to the concept of namespaces.

To simply put it, namespace is a collection of names.

In Python, you can imagine a namespace as a mapping of every name, you have defined, to corresponding objects.

Different namespaces can co-exist at a given time but are completely isolated.

A namespace containing all the built-in names is created when we start the Python interpreter and exists as long we don't exit.

This is the reason that built-in functions like id()print() etc. are always available to us from any part of the program. Each module creates its own global namespace.

These different namespaces are isolated. Hence, the same name that may exist in different modules do not collide.

Modules can have various functions and classes. A local namespace is created when a function is called, which has all the names defined in it. Similar, is the case with class. Following diagram may help to clarify this concept.

Nested Namespaces in Python Programming

什么是命名空间?

现在,我们理解了什么是名字,我们转移到命名空间的概念。

简单的说,命名空间是一个名字的集合。

在python,你可以想象一个命名空间作为每个一个名字的映射,你可以定义,对相应的对象。

不同的命名空间可以共存在一个给予的时间,但是完全独立的。

在启动Python解释器时,将创建一个包含所有内置名称的名称空间,只要不退出,该名称空间就存在。

就像内建函数id(),print()等这些原因。来自任何的部分程序总是对我们有效的。

每个模块都可以创建他们自己全局命名空间。

这不同的命名空间是独立的。因此,同样的名字可能存在不同的模块中不发生碰撞。

模块有各种各样的函数和类。一个本地命名空间被创建当一个函数被创建。该函数定义了所以名字,类也是这种情况。

下面这张图可以清晰帮助我们了解这个概念。

 Nested Namespaces in Python Programming


Python Variable Scope

Although there are various unique namespaces defined, we may not be able to access all of them from every part of the program. The concept of scope comes into play.

Scope is the portion of the program from where a namespace can be accessed directly without any prefix.

At any given moment, there are at least three nested scopes.

  1. Scope of the current function which has local names
  2. Scope of the module which has global names
  3. Outermost scope which has built-in names

When a reference is made inside a function, the name is searched in the local namespace, then in the global namespace and finally in the built-in namespace.

If there is a function inside another function, a new scope is nested inside the local scope.

变量作用域

尽管这里定义了各种各样的命名空间,但是我们不可能重程序的每部分访问他们。这程序的概念发挥了作用。

作用域是程序的一部分,它可以直接不用任何后缀访问命名空间。

在任何给定时刻,这里至少有3个内嵌作用域。

  1. 当前的函数作用域有局部名字
  2. 模块作用域有全局名字
  3. 最外层作用域具有内建名字

当在一个内部函数引用时,名字在局部命名空间被搜索,然后再去全局命名空间搜索,最后在内建空间搜索。

如果这里一个函数在另外的函数内,一个新的作用域嵌套在局部作用域。


Example of Scope and Namespace in Python

def outer_function():
    b = 20
    def inner_func():
        c = 30

a = 10

Here, the variable a is in the global namespace. Variable b is in the local namespace ofouter_function() and c is in the nested local namespace of inner_function().

When we are in inner_function(), c is local to us, b is nonlocal and a is global. We can read as well as assign new values to c but can only read b and a from inner_function().

If we try to assign as a value to b, a new variable b is created in the local namespace which is different than the nonlocal b. Same thing happens when we assign a value to a.

命名空间和作用域的例子

def outer_function():
    b = 20
    def inner_func():
        c = 30

a = 10

这里,变量a是在全局命名空间里。变量b是在outer_function(),c是内嵌到inner_function()局部命名空间。

当我们在inner_function()里,c对于我们是局部的,b不是局部的是一个全局。我们可以很好的读取已经给c赋的一个新值,但是我们在inner_function()仅仅可以读取b和c。

如果我们尝试给b赋一个值,一个新的变量b被创建在局部命名空间,同时b非局部在不同的命名空间被创建。同样的事,我们可以给a赋一个值。


However, if we declare a as global, all the reference and assignment go to the global a. Similarly, if we want to rebind the variable b, it must be declared as nonlocal. The following example will further clarify this.

def outer_function():
    a = 20
    def inner_function():
        a = 30
        print('a =',a)

    inner_function()
    print('a =',a)
     
a = 10
outer_function()
print('a =',a)

As you can see, the output of this program is

a = 30
a = 20
a = 10

然而,如果我们声明a为全局, 所有引用和赋值都执指向全局a。简单的,如果我们想重新绑定变量b,则必须要声明不是局部。一下例子将会为我们进一步介绍。

def outer_function():
    a = 20
    def inner_function():
        a = 30
        print('a = ',a)
    inner_function()
    print('a = ',a)


a = 10
outer_function()
print('a =',a)

我们可以看到,程序输出结果为

a =  30
a =  20
a = 10

In this program, three different variables a are defined in separate namespaces and accessed accordingly. While in the following program,

def outer_function():
    global a
    a = 20
    def inner_function():
        global a
        a = 30
        print('a =',a)

    inner_function()
    print('a =',a)
     
a = 10
outer_function()
print('a =',a)

The output of the program is.

a = 30
a = 30
a = 30 

Here, all reference and assignment are to the global a due to the use of keyword global.


这个程序,3个不同的变量a是分别被定义并相应访问。看下面程序

def outer_function():
    global a
    a = 20
    def inner_function():
        global a
        a = 30
        print('a =',a)
    inner_function()
    print('a =',a)
a = 10
outer_function()
print('a =',a)

下面程序输出 

a = 30
a = 30
a = 30

这里,所有引用和赋值都是对全局a的引用和赋值由于使用关键字global。 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值