2011-01-07 2 views
10

Tôi đang sử dụng danh sách mà một số chức năng hoạt động trong chương trình của tôi. Đây là một danh sách chia sẻ thực sự và tất cả các chức năng của tôi có thể chỉnh sửa nó. Có thực sự cần thiết để xác định nó là "toàn cầu" trong tất cả các chức năng?Xác định danh sách dưới dạng biến toàn cục trong Python

Tôi muốn đặt từ khóa chung đằng sau nó vào mỗi hàm sử dụng nó, hoặc định nghĩa nó bên ngoài tất cả các hàm là đủ mà không sử dụng từ toàn cục đằng sau định nghĩa của nó?

+5

Tất nhiên bạn biết rằng các biến toàn cục là eeeevil? Khi có thể, đừng viết hàm phụ thuộc vào bất cứ điều gì khác ngoài các đối số. Và không bao giờ, trừ khi trong những trường hợp rất hiếm, sửa đổi một cái gì đó toàn cầu từ hơn một điểm. Nó gần như không bao giờ cần thiết và dễ bị thêm đau đầu lớn sau này. Trong kết luận, không có giá trị nó. – delnan

Trả lời

22

Khi bạn gán biến số (x = ...), bạn đang tạo biến trong phạm vi hiện tại (ví dụ: cục bộ với hàm hiện tại). Nếu nó xảy ra để bóng một biến fron một phạm vi bên ngoài (ví dụ như toàn cầu), cũng quá xấu - Python không quan tâm (và đó là một điều tốt). Vì vậy, bạn không thể làm điều này:

x = 0 
def f(): 
    x = 1 
f() 
print x #=>0 

và mong đợi 1. Thay vào đó, bạn cần phải làm tuyên bố rằng bạn có ý định sử dụng global x:

x = 0 
def f(): 
    global x 
    x = 1 
f() 
print x #=>1 

Nhưng lưu ý rằng nhiệm vụ của một biến là rất khác nhau từ các cuộc gọi phương pháp. Bạn luôn có thể gọi các phương thức trên bất kỳ thứ gì trong phạm vi - ví dụ: trên các biến đến từ phạm vi bên ngoài (ví dụ: toàn cầu) vì không có địa phương nào che khuất chúng.

Cũng rất quan trọng: phân công thành viên (x.name = ...), mục chuyển nhượng (collection[key] = ...), chuyển nhượng lát (sliceable[start:end] = ...) và propably hơn là tất cả các phương pháp gọi là tốt! Và do đó bạn không cần global để thay đổi thành viên của toàn cầu hoặc gọi nó là phương pháp (ngay cả khi họ đột biến đối tượng).

+4

+1. Cũng cần lưu ý rằng các bài tập slice sẽ không ghi đè tham chiếu. Đặc biệt, thay vì 'x = newlist', người ta có thể làm' x [:] = new_list' và vẫn không cần dùng 'global'. Đây là khóa học được bảo hiểm theo trường hợp gọi phương thức nhưng nó đáng để chỉ ra một cách rõ ràng. – aaronasterling

+0

@aaron: Có. Mở rộng để làm rõ rằng có rất nhiều thứ (bao gồm gán thành viên, phân bổ lát, vv) thực sự là các cuộc gọi phương thức. – delnan

4

Có, bạn cần sử dụng global foo nếu bạn định ghi vào đó.

foo = [] 

def bar(): 
    global foo 
    ... 
    foo = [1] 
+1

Trong khi không hoàn toàn sai (trong ví dụ, 'toàn cầu' là cần thiết), điều này là gây hiểu lầm. Đối với người mới bắt đầu, nhiều người dường như không đồng ý với khái niệm của Python khi bạn "viết thư cho nó". – delnan

+0

cảm ơn, đây cũng là trường hợp cho từ điển? – Hossein

+2

@Hossein: Điều này cũng giống nhau đối với bất kỳ biến nào. Đối tượng được tham chiếu không quan trọng. – delnan

1

Không, bạn có thể chỉ định danh sách làm đối số từ khóa cho hàm của mình.

alist = [] 
def fn(alist=alist): 
    alist.append(1) 
fn() 
print alist # [1] 

Tôi cho rằng đó là thực tế không tốt. Loại quá hung hãn. Nếu bạn thực sự cần sử dụng cấu trúc dữ liệu giống như singleton có sẵn trên toàn cầu, tôi sẽ sử dụng phương pháp biến cấp mô-đun, tức là đặt 'alist' vào mô-đun và sau đó trong các mô-đun khác của bạn nhập biến đó:

Trong tệp foomodule.py:

alist = [] 

Trong file barmodule.py:

import foomodule 
def fn(): 
    foomodule.alist.append(1) 
print foomodule.alist # [1] 
+0

Làm rõ: "Globals" là * luôn luôn * cấp mô-đun. Không cần phải đặt nó vào một mô-đun bổ sung (đôi khi hữu ích hoặc ngữ nghĩa chính xác hơn mặc dù). – delnan

+0

Tôi không biết về những phức tạp liên quan. Có vẻ như hai ví dụ mà tôi đã viết là không cần thiết chút nào nếu tất cả những gì bạn muốn làm là sửa đổi một biến cấp mô-đun (nghĩa là, không tạo một gán cho tên toàn cầu). Xem câu trả lời của delnan cho một đánh giá tốt hơn nhiều. – XORcist