Fork me on GitHub

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc

起因: 想利用模块传递某个变量,修改某个变量的值,且在其它模块中也可见

于是我做了这样一个实验:
git@github.com:vearne/test_scope.git

base.py

value = 10

b.py

import base
def hello():
    print 'scope base', base.value, id(base.value)

main.py

from base import value
from b import hello
print 'scope base', value, id(value)
value = 20
print 'scope local', value, id(value)
hello()

运行python main.py
输出结果如下:

['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'hello', 'value']
scope base 10 140195531889072
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'hello', 'value']
scope local 20 140195531888832
scope base 10 140195531889072

大家可以看出,value 的值并没有被修改,并且id值(对象的内存地址) 不一致,因此我们得出结论, value 和 base.value 存在在不同位置,是两个不同的对象。
阅读python官方文档
https://docs.python.org/2/tutorial/modules.html
我找到这样一段话

Each module has its own private symbol table, which is used as the global symbol table by all functions defined in the module. Thus, the author of a module can use global variables in the module without worrying about accidental clashes with a user’s global variables. On the other hand, if you know what you are doing you can touch a module’s global variables with the same notation used to refer to its functions, modname.itemname.

Modules can import other modules. It is customary but not required to place all import statements at the beginning of a module (or script, for that matter). The imported module names are placed in the importing module’s global symbol table.

每个模块有一个自己的符号表,当我们引入一个模块时,这个符号表中的内容就会被修改,使用dir() 可以查看当前模块的符号表中的符号列表
看下面的列子:

print '------------------'
a = 15
print dir()
print '------------------'
import math
print dir()
print '------------------'
from datetime import timedelta
print dir()

运行结果如下:

------------------
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a']
------------------
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'math']
------------------
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'math', 'timedelta']

最后回到前面的例子:

from base import value
value = 20  # 这里我们并没有修改模块base中value的值,而是重新定义了一个本地变量, 并且符号表中的指向已经被修改了(指向一个本地变量value)
...

其实这么看python的模块还有点像命名空间,隔离同名变量,防止命名冲突

参考资料:
https://docs.python.org/2/library/datetime.html

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注