从多个Python文件中更改相同的文件范围变量

从多个Python文件中更改相同的文件范围变量,python,Python,看起来,如果我通过import语句从多个文件导入同一个Python文件,并更改其中的某个文件范围变量,那么引用更改对其他模块将不可见,而容器更改将不可见 比如说, 第一个示例 first.py import reader import helper reader.change_buf('modified') helper.foo() import reader def foo(): print(reader.BUF) buf = 'original' def change_b

看起来,如果我通过
import
语句从多个文件导入同一个Python文件,并更改其中的某个文件范围变量,那么引用更改对其他模块将不可见,而容器更改将不可见

比如说,

第一个示例

first.py

import reader
import helper


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


def foo():
  print(reader.BUF)
buf = 'original'


def change_buf(buf):
  buf = buf
import reader
import helper


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


def foo():
  print(reader.BUF)
buf = ['0', '1', '2']


def change_first_element(new_elem):
  buf[0] = new_elem
second.py

import reader
import helper


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


def foo():
  print(reader.BUF)
buf = 'original'


def change_buf(buf):
  buf = buf
import reader
import helper


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


def foo():
  print(reader.BUF)
buf = ['0', '1', '2']


def change_first_element(new_elem):
  buf[0] = new_elem
reader.py

import reader
import helper


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


def foo():
  print(reader.BUF)
buf = 'original'


def change_buf(buf):
  buf = buf
import reader
import helper


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


def foo():
  print(reader.BUF)
buf = ['0', '1', '2']


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

> python first.py
original
> python first.py
['1', '1', '2']
第二个示例

first.py

import reader
import helper


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


def foo():
  print(reader.BUF)
buf = 'original'


def change_buf(buf):
  buf = buf
import reader
import helper


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


def foo():
  print(reader.BUF)
buf = ['0', '1', '2']


def change_first_element(new_elem):
  buf[0] = new_elem
second.py

import reader
import helper


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


def foo():
  print(reader.BUF)
buf = 'original'


def change_buf(buf):
  buf = buf
import reader
import helper


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


def foo():
  print(reader.BUF)
buf = ['0', '1', '2']


def change_first_element(new_elem):
  buf[0] = new_elem
reader.py

import reader
import helper


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


def foo():
  print(reader.BUF)
buf = 'original'


def change_buf(buf):
  buf = buf
import reader
import helper


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


def foo():
  print(reader.BUF)
buf = ['0', '1', '2']


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

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

为什么?

tl;dr,因为你用不同的行为做不同的事情。

  • 在第一个示例中,您在函数
    change_buf
    中创建了一个局部变量
    buf
    ;在第二个示例中,本地没有这样的变量可访问,因此python将堆栈向上向下搜索适合您的请求的变量,并在模块级范围内找到一个
  • 第一个示例使用赋值语句,第二个语句是fancy
    setitem
    notation。这两个人的行为是不同的

  • 解释(1)中的行为。如果要使用赋值语句显式访问全局变量,请使用

    从文档中:

    如果没有全局变量,就不可能分配给全局变量,尽管自由变量可能引用全局变量而不声明为全局变量

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

    foo = [3]
    def set_foo():
        foo.__setitem__(0,3)
    
    现在您可以看到,
    foo
    是一个被引用的“自由变量”,并且只能以该名称引用全局范围元素。如果对
    foo
    属于哪个范围存在任何歧义,python将无法处理您的情况



    Python关于作用域的规则可能有点复杂,因为在第一个示例中,您将全局变量
    buf
    隐藏在局部变量(函数参数
    buf
    )后面,而在第二个示例中,函数参数(
    new_elem
    )不会冲突。但这还不是全部。在第一个示例中,您在函数中定义了变量
    buf
    ,因此它在默认情况下仍然是局部变量-在第二个示例中,您使用它是因为您设置了
    buf[0]
    。您必须将其声明为全局

    您应该这样编写reader.py:

    buf = 'original'
    
    def change_buf(new_val):
        global buf
        buf = new_val