2010-08-27 101 views
6

Vì vậy, tôi đang cố tạo một danh sách lồng nhau trong Python dựa trên chiều rộng và chiều cao. Đây là những gì tôi có cho đến thời điểm này:Python - Danh sách lồng nhau động

width = 4 
    height = 5 
    row = [None]*width 
    map = [row]*height 

Bây giờ, điều này rõ ràng là không hoàn toàn đúng. Khi in có vẻ tốt đẹp:

[[None, None, None, None], 
[None, None, None, None], 
[None, None, None, None], 
[None, None, None, None], 
[None, None, None, None]] 

Nhưng cố gắng để gán giá trị cho một vị trí như vậy:

map[2][3] = 'foo' 

tôi nhận được:

[[None, None, None, 'foo'], 
[None, None, None, 'foo'], 
[None, None, None, 'foo'], 
[None, None, None, 'foo'], 
[None, None, None, 'foo']] 

Rõ ràng điều này xảy ra bởi vì mỗi sublist thực sự là chỉ tham chiếu cùng một đối tượng, hàng, để thay đổi một, thay đổi tất cả. Vì vậy, đây là gần nhất tôi đã có!

Làm cách nào để tạo động danh sách lồng nhau? Cảm ơn!

+0

Trong khi không phải là một bản sao chính xác, xem: http://stackoverflow.com/questions/1605024/python-using-the-multiply-operator-to -create-copy-of-objects-in-list – carl

+2

'map()' là một hàm dựng sẵn, nó không phải là một ý tưởng tốt để ghi đè nó. Tìm một tên khác, nếu cần bạn chỉ có thể nối thêm '_'. –

Trả lời

11

Khi bạn thực hiện [row]*height, bạn kết thúc với cùng một đối tượng danh sách trong mỗi hàng. Tham chiếu mảng row được lặp lại trong mỗi hàng có nghĩa là mỗi hàng thực sự trỏ đến cùng một đối tượng danh sách. Do đó sửa đổi một hàng thực sự sửa đổi tất cả các hàng.

Hãy xem điều gì xảy ra khi bạn in id() cho mỗi hàng. Chúng đều giống nhau!

>>> grid = [[None] * width] * height 
>>> [id(row) for row in grid] 
[148014860, 148014860, 148014860, 148014860, 148014860] 

Bạn có thể tạo python để tạo danh sách riêng biệt nhưng không giống nhau cho mỗi hàng bằng cách sử dụng danh sách hiểu. Khi bạn sử dụng [rowexpr for i in xrange(height)] thì rowexpr sẽ được đánh giá một lần mỗi hàng. Bí quyết sau đó là sử dụng một biểu thức sẽ dẫn đến một danh sách duy nhất mỗi khi nó được đánh giá.

này sẽ có ý nghĩa hơn nếu bạn nhìn thấy nó trong hành động:

>>> grid = [[None] * width for i in xrange(height)] 
>>> grid[2][3] = 'foo' 
>>> grid 
[[None, None, None, None], 
[None, None, None, None], 
[None, None, None, 'foo'], 
[None, None, None, None], 
[None, None, None, None]] 

Mỗi lần [None] * width được đánh giá nó tạo ra một danh sách mới.

>>> [id(row) for row in grid] 
[148016172, 148015212, 148016236, 148016108, 148016332] 
0

tôi sử dụng một cái gì đó như thế này:

w = 5 
h = 5 

map = [] 

for i in range(h): 
row = [] 
for j in range(w): 
    row.append(None) 
map.append(row) 

print map 

map[2][3] = 'foo' 

print map 
+0

Việc hiểu danh sách là cách đúng __one__ để thực hiện việc này. – aaronasterling

+0

Tôi đồng ý, việc hiểu danh sách càng rõ ràng, dễ đọc hơn, nhiều hơn 'Pythonic'. Cách của tôi chỉ là một cách để giải quyết vấn đề và cũng có thể đọc được cho mọi người (như tôi), những người vẫn đang phát triển từ C sang python. – lalli

+0

làm điều đó với lồng nhau cho các vòng không giúp bạn hoặc bất cứ ai khác thực hiện việc chuyển đổi từ C sang python: Nó chỉ bị cản trở. – aaronasterling

Các vấn đề liên quan