2013-03-06 27 views
11

Chỉ cần nhầm lẫn về giá trị toàn cầu bằng Python, đây là hai đoạn mãTại sao reset python giá trị toàn cầu không có hiệu lực

#gl.py 

import cli 

a = 1  
print "gl 1: %d %d" % (id(a), a) 


def reset(): 
    global a 
    a = 7 
    print "reset 1: %d %d" % (id(a), a) 


if __name__ == '__main__': 
    cli.handler(reset) 
    print "gl 2: %d %d" % (id(a), a) 

mã cli

#cli.py 

def handler(func): 
    from gl import a 
    print "cli 1: %d %d" % (id(a), a) 
    func() 
    print "cli 2: %d %d" % (id(a), a) 

Kết quả của việc thực hiện là

$ python gl.py 
gl 1: 150847672 1 
gl 1: 150847672 1 
cli 1: 150847672 1 
reset 1: 150847600 7 
cli 2: 150847672 1 #Why value doesn't change 
gl 2: 150847600 7 

Ở đây tôi không hiểu sau khi thực hiện "đặt lại chức năng()", kết quả của giá trị toàn cầu không thay đổi trong cli.py (cli 2: 150847672 1), nhưng trở lại gl.py, giá trị toàn cầu không thay đổi !!

+2

Thay đổi nhập thành 'nhập gl' và tham chiếu đến' a' là 'gl.a'. Biến toàn cục chỉ là toàn cục đối với mô-đun 'gl'. Quá trình nhập của bạn tạo bản sao cục bộ. –

+0

@Steven Tôi cũng nghĩ như vậy, nhưng một thử nghiệm nhanh cho thấy rằng đó không phải là trường hợp.Cũng tốt, câu hỏi thú vị từ một người dùng tương đối mới - hoan nghênh! – Voo

+0

Nhưng tại sao nó phải thay đổi? Bạn đang nhập a = 1 và đó là bản in 1. Chỉ cần thử hiểu cách hoạt động của các loại bất biến và cách tham chiếu công việc và thu gom rác thải. Toàn bộ những điều này bạn có thể tìm thấy trong phần đầu của cuốn sách Mark Lutz được gọi là "Bắt đầu với python" hoặc một cái gì đó giống nhau. – Denis

Trả lời

2

mô-đun gl bạn đã được nhập gấp đôi thành hai không gian tên khác nhau

thử điều này:

import sys 
print sys.modules['__main__'].a 
print sys.modules['gl'].a 
4

Hai khái niệm đang thiếu ở đây

  • Globals là globals để mô-đun và không qua module

Tham khảo: http://legacy.python.org/doc/essays/ppt/hp-training/sld036.htm

Tham khảo: http://docs.python.org/release/2.4/ref/global.html

  • biến được nhập khẩu như giá trị và không bằng cách tham khảo

Tham khảo: https://stackoverflow.com/a/3338357/977038

Nếu bạn cần chia sẻ các biến toàn cầu qua module tham khảo How do I share global variables across modules?

2

Các gl bạn nhập khẩu trong cli thực sự là một bản sao của đối tượng mô-đun. nếu chúng ta thay đổi mã của bạn như thế này:

#gl.py 

import cli 
import sys 

a = 1  
print "gl 1: %d %d" % (id(a), a) 
print "gl id on import: {0}".format(id(sys.modules[__name__])) 


def reset(): 
    global a 
    a = 7 
    print "gl id in reset: {0}".format(id(sys.modules[__name__])) 
    print "reset 1: %d %d" % (id(a), a) 

def printa(): 
    print "gl: %d %d" % (id(a), a) 

if __name__ == '__main__': 
    cli.handler(reset) 
    print "gl id in main: {0}".format(id(sys.modules[__name__])) 
    print "gl 2: %d %d" % (id(a), a) 

#cli.py 

def handler(func): 
    #from gl import a 
    import gl 
    print "gl id in cli: {0}".format(id(gl)) 
    print "cli 1: %d %d" % (id(gl.a), gl.a) 
    func() 
    print "cli 2: %d %d" % (id(gl.a), gl.a) 
     gl.reset() 
     print "cli 3: %d %d" % (id(gl.a), gl.a) 

Chúng tôi nhận được:

gl 1: 19056568 1 
gl id on import: 140075849968728 
gl 1: 19056568 1 
gl id on import: 20004096 
gl id in cli: 20004096 
cli 1: 19056568 1 
gl id in reset: 140075849968728 
reset 1: 19056424 7 
cli 2: 19056568 1 
gl id in reset: 20004096 
reset 1: 19056424 7 
cli 3: 19056424 7 
gl id in main: 140075849968728 
gl 2: 19056424 7 

Vì vậy, khi chúng tôi chạy reset, chúng ta thay đổi tài liệu tham khảo

a -> 19056568 

đến

a -> 19056424 

nhưng chỉ trong một bản sao gl. Một trong những khác (một trong cli) giữ vào tài liệu tham khảo cũ. Nếu chúng ta chạy gl.reset() từ bên trong cli, tham chiếu trên bản sao đó thay đổi và chúng ta nhận được sự thay đổi mong đợi trong cli.