2016-04-25 60 views
2

似乎如果我通过几个文件中的import语句导入同一个Python文件并在其中更改某个文件范围变量,那么引用更改对其他模块将不可见而容器的变化将会。从几个Python文件中更改相同的文件范围变量

例如,

第一示例

first.py

import reader 
import helper 


reader.change_buf('modified') 
helper.foo() 

second.py

import reader 


def foo(): 
    print(reader.BUF) 

reader.py

buf = 'original' 


def change_buf(buf): 
    buf = buf 

输出

> python first.py 
original 

第二示例

first.py

import reader 
import helper 


reader.change_first_element('1') 
helper.foo() 

second.py

import reader 


def foo(): 
    print(reader.BUF) 

reader.py

buf = ['0', '1', '2'] 


def change_first_element(new_elem): 
    buf[0] = new_elem 

输出

> python first.py 
['1', '1', '2'] 

为什么?

回答

0

tl; dr因为你对不同的行为做了不同的事情。

  1. 在你的第一个例子,在新建功能change_buf一个局部变量buf;在第二个例子中,没有这样的变量可以在本地访问,所以python会向下搜索堆栈,寻找适合您请求的变量,并在模块级范围中找到一个变量。
  2. 您的第一个示例使用赋值语句,您的第二个语句是花式setitem表示法。这两种行为是不同的。

解释(1)中,This question is similar的行为。如果你想使用赋值语句明确访问一个全局变量,使用global or nonlocal keywordas is done here

从文档:

这将是不可能分配到一个全局变量没有全球性的,但免费变量可以指全局变量而不被声明为全局变量。

请注意,您的第二个示例不是一个赋值语句;它是一个调用__setitem__的变量buf的方法,这恰好是类型列表。它可能会更有意义看起来像这样

foo = [3] 
def set_foo(): 
    foo.__setitem__(0,3) 

现在你看到foo被参考的“自由变量”,并能来引用该名称在全球范围内的元素。如果对于属于哪个范围foo有任何不明确性,python将无法处理您的案例。


Python的约作用域可以稍微复杂的规则,but are unambiguous

0

很简单,因为在第一个例子中,你都躲在全局变量buf后的本地一个(函数参数buf),而在第二个例子中,功能参数(new_elem)不会发生碰撞。但那不是全部。在第一个例子中,你定义了变量buf在一个函数中,所以它仍然是本地的默认 - 在第二个例子中,你自己使用它自从你设置了buf[0]。您必须声明它global

你应该写reader.py这样:

buf = 'original' 

def change_buf(new_val): 
    global buf 
    buf = new_val