何时使用id()获取不同子进程中全局变量的标识返回相同的值,但是当我在子进程中修改全局变量但在主进程中不起作用时?如果id()返回变量的实际内存地址,但是为什么我不能在子进程中修改值? (我在MacOS中使用Python3.6 [CPython])
import os
from multiprocessing import Process
Global_list = []
Global_number = 0
def foo(x):
global Global_list, Global_number
print("Pid {}, id(Global_list)={}, id(Global_number)={}".format(os.getpid(), id(Global_list), id(Global_number)))
Global_list.append(x)
Global_number += x
print("After: Pid {}, id(Global_list)={}, id(Global_number)={}\n".format(os.getpid(), id(Global_list), id(Global_number)))
if __name__ == '__main__':
la = [1, 2, 3, 4]
p_list = []
for i in la:
process = Process(target=foo, args=(i,))
p_list.append(process)
process.start()
for p in p_list:
p.join()
print("In main process, id(Global_list)={}, id(Global_number)={}".format(id(Global_list), id(Global_number)))
print("After all: Global_list={}, Global_number={}".format(Global_list, Global_number))
结果:
Pid 42061, id(Global_list)=4347140936, id(Global_number)=4305316864
After: Pid 42061, id(Global_list)=4347140936, id(Global_number)=4305316896
Pid 42062, id(Global_list)=4347140936, id(Global_number)=4305316864
After: Pid 42062, id(Global_list)=4347140936, id(Global_number)=4305316928
Pid 42063, id(Global_list)=4347140936, id(Global_number)=4305316864
After: Pid 42063, id(Global_list)=4347140936, id(Global_number)=4305316960
Pid 42064, id(Global_list)=4347140936, id(Global_number)=4305316864
After: Pid 42064, id(Global_list)=4347140936, id(Global_number)=4305316992
In main process, id(Global_list)=4347140936, id(Global_number)=4305316864
After all: Global_list=[], Global_number=0
答案 0 :(得分:0)
>>> Global_list = []
>>> id(Global_list)
4351947464
>>> Global_list.append(1)
>>> id(Global_list)
4351947464
>>> Global_number = 0
>>> id(Global_number)
4305328480
>>> Global_number += 1
>>> id(Global_number)
4305328512 ----> different address
如果尝试为相同的变量名称分配值,则其内存地址将更改。
答案 1 :(得分:0)
您似乎有一个基本的误解。 在同一过程中,如果id()
为两个不同的对象返回相同的值,则意味着它们具有相同的对象标识(对另一个对象的修改将对另一个对象可见)。>
id()
仅在一个进程中是唯一的。如果您正在使用多个进程,则可以(很可能会!)让id()
为不同对象返回相同的值,该值可能是相同的类型,甚至可能具有相同的值(例如,如果您使用os.fork()
创建子流程),但 not 具有相同的标识:对一个的更改不会反映在另一个中。
更笼统地说,在所有现代操作系统中都是如此:每个进程都有其自己独立的内存“视图”(称为“虚拟内存”),并且可以使用其喜欢的任何地址(受各种操作系统级别的限制,例如sbrk
或mmap
)。系统中的每个进程都可以在地址4347140936处有一个对象,并且它们都可以是彼此不同的对象。许多操作系统都依赖于这种行为-例如,共享库可能总是在同一位置加载到内存中,而调用共享库的函数可能取决于实际情况。
也就是说,如果您正在使用各种共享内存或对象远程处理机制,则可以 在一个进程中对对象进行修改,从而将其反映到另一个进程中的对象。但是在那种情况下,实际上您有两个 对象,只有两个“互连”对象-这意味着id()
将返回不同值,即使对象在概念上是“相同的”。