web-dev-qa-db-ja.com

ループ内のリストアイテムの変更(Python)

Forループを使用してリスト内のアイテムを変更しようとしていますが、エラーが発生します(以下を参照)。サンプルコード:

#!/usr/bin/env python
# *-* coding: utf8 *-*

data = []
data.append("some")
data.append("example")
data.append("data")
data.append("here")

for item in data:
    data[item] = "everything"

エラー:

Traceback (most recent call last):
  File "./testy.py", line 11, in <module>
    data[item] = "everything"
TypeError: list indices must be integers, not str

この問題を解決する方法はありますか?

29

代わりにこれを試してください:

_for i in xrange(len(data)):
    data[i] = "everything"
_

あなたが持っている基本的な問題は、dataがリストである_data[i]_を書くとき、iは整数、リストへの数値インデックスである必要があるということです。しかし、ループで

_for item in data
_

itemは、リストにある実際の物、つまり、物の数値インデックスではなく、文字列です。 xrangeは、リスト内の値の代わりに数値を生成する反復子なので、それを使用できます。

代替案は

_for i, _ in enumerate(data):
    data[i] = "everything"
_

enumerate関数は、フォーム_(index, item)_のタプルの反復子を提供します。したがって、必要なことは、インデックスを取得してその項目を忘れることだけです。リストがその長さを変数に保存しているため、リストにアクセスせずにすばやくアクセスできるため、どちらの方法(enumerateまたはxrange)が大幅に高速化または改善されるかはわかりません。リスト要素を数えます。

ただし、新しいリスト値を計算するために古いリスト値が必要な場合、Pythonがリスト内の要素をルックアップすることを避けるため、enumerateの方法はおそらくわずかに高速になります。

_for i, item in enumerate(data):
    data[i] = func(item)
_

ただし、このようなことはリストの内包表記としてより適切に表現されます。

_data = [func(item) for item in data]
_

これを行うと、Pythonがdataの各アイテムを通過し、それに関数を適用し、結果から新しいリストを自動的に構築するので、心配する必要はありません。 func(item)の結果をリストの適切な場所に配置します。元の例は、実際には次のように表現できます。

_data = ["everything" for item in data]
_
70
David Z

リスト項目は整数インデックスによってアクセスされます。 e。あなたの例では_data[1] == 'example'_。これが、文字列をルックアップとして使用しているときにPythonが文句を言う理由です。

値でリスト内の要素を検索する場合は、data.index("value")を使用できます。

_data[data.index("some")] = "something else"
_

ただし、それらをループするだけの場合は、Davidが提案したようにenumerate()を使用します。

5
Tim Pietzcker

整数を使用したリストのインデックス付けは非効率的です。 pythonは、基になるポインタを持つリンクテーブルを使用してリスト要素を格納します。この場合、特定のアイテムを見つけるには、pythonまでリストを走査する必要がありますi番目のアイテム。

このような形式を使用すると効率的である可能性があります:a [:] = [x * x for a]

0
Jingpeng Wu