Đối tượng bản đồ Python không thể thay thế được


82

Tại sao đoạn mã sau lại mắc lỗi:

payIntList[i] = payIntList[i] + 1000
TypeError: 'map' object is not subscriptable

payList = []
numElements = 0

while True:
        payValue = raw_input("Enter the pay amount: ")
        numElements = numElements + 1
        payList.append(payValue)
        choice = raw_input("Do you wish to continue(y/n)?")
        if choice == 'n' or choice == 'N':
                         break

payIntList = map(int,payList)

for i in range(numElements):
         payIntList[i] = payIntList[i] + 1000
         print payIntList[i]

5
Bạn có đang sử dụng Python 3 không?
Felix Kling,

@ user567797 - Điều này hoạt động tốt với tôi @ Felix: Anh ấy không sử dụng python 3 vì anh ấy đang sử dụng print làm câu lệnh!
Pushpak Dagade,

2
Toàn bộ nội dung bên dưới vòng lặp while có thể được rút ngắn thành payIntList = [int(x) + 1000 for x in payList]; print(*payIntList, sep='\n')(hoặc for x in payIntList: print xtrong Python 2.x nơi printkhông phải là một hàm) mà không làm mất khả năng đọc (có thể cho là nó thậm chí còn dễ đọc hơn).

2
@Guanidene: Anh ấy đang sử dụng Python 3, vì anh ấy có các đối tượng bản đồ. Nhưng anh ta đang cố gắng chạy mã Python 2 trên đó, do đó xảy ra lỗi.
Lennart Regebro

3
Tôi muốn một câu hỏi "Tại sao tôi gặp lỗi khi chạy mã Python 2 trên Python 3", mà chúng tôi có thể đánh dấu tất cả những điều này là trùng lặp. ;)
Lennart Regebro

Câu trả lời:


136

Trong Python 3, maptrả về một đối tượng kiểu có thể lặp lại map, chứ không phải danh sách có thể mô tả được, điều này sẽ cho phép bạn viết map[i]. Để buộc một kết quả danh sách, hãy viết

payIntList = list(map(int,payList))

Tuy nhiên, trong nhiều trường hợp, bạn có thể viết mã của mình đẹp hơn bằng cách không sử dụng các chỉ mục. Ví dụ, với khả năng hiểu danh sách :

payIntList = [pi + 1000 for pi in payList]
for pi in payIntList:
    print(pi)

6
Câu trả lời này đúng, nhưng lý tưởng nhất là bạn sẽ không chuyển đổi bản đồ thành danh sách cho các trường hợp sử dụng như thế này. Bản đồ đã có thể lặp lại và dường như là một thứ tự có cường độ nhanh hơn để lặp lại so với danh sách. Vì vậy, bạn không những không cần chỉ mục mà còn không cần danh sách. Mã sạch sẽ, vì payIntList đã là một bản đồ,for i in payIntList: print(i + 1000)
RustyToms

17

map() không trả về danh sách, nó trả về map đối tượng.

Bạn cần gọi list(map) nếu bạn muốn nó trở thành danh sách.

Thậm chí còn tốt hơn,

from itertools import imap
payIntList = list(imap(int, payList))

Sẽ không chiếm nhiều bộ nhớ khi tạo một đối tượng trung gian, nó sẽ chỉ chuyển ints ra ngoài khi nó tạo ra chúng.

Ngoài ra, bạn có thể làm if choice.lower() == 'n': để không phải làm hai lần.

Python hỗ trợ +=: bạn có thể làm payIntList[i] += 1000numElements += 1 nếu bạn muốn.

Nếu bạn thực sự muốn trở nên khôn lanh:

from itertools import count
for numElements in count(1):
    payList.append(raw_input("Enter the pay amount: "))
    if raw_input("Do you wish to continue(y/n)?").lower() == 'n':
         break

và / hoặc

for payInt in payIntList:
    payInt += 1000
    print payInt

Ngoài ra, bốn dấu cách là số lượng thụt lề tiêu chuẩn trong Python.


1
Đó là trường hợp của python3, nhưng ở đây anh ta dường như đang sử dụng python2.x vì anh ta đang sử dụng print làm câu lệnh.
Pushpak Dagade

Đoạn mã của bạn không lưu trữ tất cả các int trong bộ nhớ trong một danh sách. Sử dụng trình vòng lặp thực sự hữu ích và tiết kiệm bộ nhớ, đặc biệt là với nhiều lớp biến đổi, nhưng việc thêm listxung quanh trình vòng lặp sẽ lấy đi lợi thế đó!

1
Khi bạn làm điều list(map(...))đó sẽ tạo một map, sau đó tạo một list, sau đó xóa dấu map, vì vậy trong một thời gian, cả hai đều nằm trong bộ nhớ cùng một lúc. Khi bạn làm list(imap(...))điều này không đúng như vậy. Đó là lý do tại sao tôi nói "mất trí nhớ với một trung gian đối tượng"
AGF

Vì vậy, bạn đang giả sử Python 2? Sau đó list(map(...))là thừa, bởi vì - như tài liệu nói, "kết quả [của map] luôn là một danh sách".
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.