2013-01-07 39 views
5

Tôi đang học Python và đã cố gắng để làm cho một deque. Tuy nhiên, tôi nhận được đầu ra không chính xác và tôi không chắc chắn tại sao. Mã của tôi là như sau:Phạm vi deque của Python?

p = [2, 1], [1, 1] 
init_q= deque() 

init_q.append(p) 
for i in range(len(p)): 
    for j in range(len(p[i])): 
     temp = p[i][j] 
     p[i][j] = 0 
     init_q.append(p) 
     p[i][j] = temp 

while init_q: 
    print init_q.pop() 

Trong mã này tôi mất trong một danh sách, sau đó tôi muốn tạo một hàng đợi với 5 danh sách, 4 trong số đó có một 0 trong họ tại các địa điểm khác nhau, kết quả tôi muốn là :

([2, 1], [1, 1]) 
([0, 1], [1, 1]) 
([2, 0], [1, 1]) 
([2, 1], [0, 1]) 
([2, 1], [1, 0]) 

Tuy nhiên, kết quả tôi nhận được là:

([2, 1], [1, 1]) 
([2, 1], [1, 1]) 
([2, 1], [1, 1]) 
([2, 1], [1, 1]) 
([2, 1], [1, 1]) 
+0

Bạn có chắc chắn rằng đầu ra dự kiến ​​không bị lạc hậu? – abarnert

Trả lời

3

Tôi đã tạo một visualization trên Python Tutor bằng cách đơn giản hóa mã của bạn. Fiddle xung quanh và bạn có thể dễ dàng nhìn thấy những gì đang xảy ra.

Thay đổi một dòng cho mã của bạn có thể khắc phục điều này.

init_q.append(map(list, p)) # Initialize a new list from p's element lists 

Đây là visualization bằng cách sử dụng thay đổi ở trên.

4

Bạn đang đặt một đối tượng trong deque, sau đó thay đổi các đối tượng. Trong thực tế, bạn luôn đặt cùng một đối tượng vào deque, vì vậy tất cả các deque có tham chiếu đến một đối tượng p.

+0

Và để giải quyết vấn đề này, bạn sẽ ...? –

+2

Tạo một bản sao của đối tượng - 'p [:]', hoặc nếu nó không thực hiện, hãy tạo một 'bản sâu 'của danh sách bằng cách sử dụng mô-đun' copy', và sau đó nối thêm * bản sao * vào danh sách. – Volatility

+0

Cảm ơn tôi không biết mình đang tìm gì nhưng tôi đã giải quyết. 'p [:]' không hoạt động, nhưng 'deepcopy' đã làm. Vì vậy, nó bây giờ trông giống như: 'newobj = copy.deepcopy (p)' 'newobj [i] [j] = 0' ' init_q.append (newobj) ' – Sjieke

1

Theo dõi nhận xét của tôi để trả lời Ned Batchelder của, dưới đây là cách bạn có thể làm điều tương tự bất biến:

for i in range(len(p)): 
    for j in range(len(p[i])): 
     temprow = [0 if y==j else p[i][y] for y in range(len(p[i]))] 
     temp = [temprow if x==i else p[x] for x in range(len(p))] 
     init_q.append(temp) 

Trong trường hợp này, tôi nghĩ rằng kết quả là ít hơn rất nhiều có thể đọc được hơn đề nghị của ông:

 temp = copy.deepcopy(p) 
     temp[i][j] = 0 
     init_q.append(temp) 

Như tôi đã nói, đôi khi nó làm cho mọi thứ trở nên đơn giản hơn, đôi khi ít đơn giản hơn… Nhưng vấn đề là dễ dàng hơn để giải thích. Bạn không phải lo lắng về việc có nhiều số list s trong số init_q —hoặc, tệ hơn, phụ trong số list trong số những người list s — đang chia sẻ danh tính.

Liệu sự cân bằng có đáng giá hay không thực sự là quyết định từng trường hợp và có thể khác nhau đối với từng lập trình viên. Trong trường hợp này, tôi sẽ không sử dụng giải pháp bất biến, và tôi nghi ngờ nhiều lập trình viên (Python) khác sẽ làm như vậy. Nhưng đáng để biết cách viết nó.

Bạn cũng có thể xem xét việc viết danh sách này dưới dạng danh sách 3D, thay vì loại bỏ danh sách 2D và sau đó cho nó vào deque. Đó rõ ràng là tương đương, nhưng khái niệm nó có thể đơn giản hơn để nghĩ về cách này:

init_q.append(p) 
q = [copy.deepcopy(p) for i in range(len(p)) for j in range(len(p[i]))] 
for i in range(len(p)): 
    for j in range(len(p[i])): 
     q[i*len(p[i])+j][i][j] = 0 
init_q.extend(q) 

PS, nếu bạn đang làm rất nhiều loại điều, bạn có thể muốn có một cái nhìn tại numpy. Nếu đây là toàn bộ vấn đề của bạn, nó sẽ không làm bạn tốt ... nhưng nếu bạn làm bất cứ điều gì phức tạp hơn với mảng đa chiều, nó sẽ.