我有一个二维列表,列表中的元素是以字符串
为元素的列表。
由于这些字符串表示的是数字,我想把这些字符串都转换成float
型。
def loadCsv(filename):
# 取出数据
lines = csv.reader(open(filename, 'rb'))
# 存入dataset
dataset = list(lines)
for data in dataset:
for i in data:
i = float(i) #为什么执行了该语句后i不变?
return dataset
上面这段程序执行后dataset不变,为什么i = float(i)
不能改变i的值呢?
虽然我知道这样写不是好习惯,但是想问python里for语句中所遍历的对象并不是在原对象上修改?
def loadCsv(filename):
# 取出数据
lines = csv.reader(open(filename, 'rb'))
# 存入dataset
dataset = list(lines)
for i in range(len(dataset)):
dataset[i] = [float(x) for x in dataset[i]]
return dataset
这段程序能够成功,又是为什么呢?
変数はオブジェクトへの単なるポインタです
それを理解してから読み続けてください。
最初のタイプ: トラバーサル中に、i という名前のポインターが作成され、データ内の要素を指します。 i=float(i) を実行するときは、新しいオブジェクト float(i) を作成し、i にそれをポイントさせるだけです。
2番目と同様。
正確に言うと、
2 つ目は、元のリストを直接操作するためです:i = float(i)
はi
の値を変更しますが、i
はdata
要素の単なるコピーであり、次のようにdata
の値を変更しません。 リーリーリーリー
Python では、for を介してオブジェクトを走査するとき、走査されたオブジェクト自体を変更することはできません。これは一般的な規則です。
一般に、次の要素は next() メソッドを通じて取得されます。
トラバーサル オブジェクトの変更が許可されている場合、要素の順序に影響し、次の各ステップの結果が制御不能になります。
enumerate を使用して変更することを検討してください。
追加情報については、公式 Python マニュアルの for ステートメントの説明を参照してください:
https://docs.python.org/2/reference/compound_stmts.html#the-for-statement
Python の
上記のプログラムは、反復ごとにfor
トラバーサルでは、トラバーサル オブジェクト自体を直接変更することは通常推奨されません (不可能ではありません)。これは、次のような問題が発生するためです。 リーリーの長さが増加するため、無限ループに入ります。そのため、
の値を変更し、トラバースを正常に完了できます。n
を使い果たすことはできないため、通常は反復オブジェクトのコピーを使用して走査します。 リーリーfor
このようにして、n
次に、例の最初のプログラムに戻ります。実際、
の前後 2 つは同じオブジェクトをまったく参照していません。後者のは
は、i = float(i)
の要素であり、前者のi
は のローカル変数です。data
スコープ。これには Python 言語の設計において不合理な点が含まれています。プログラムを見てみましょう:i
リーリーloadCsv
つまり、反復に参加している識別子ループを終了した後もリサイクルされておらず、反復の最後の値との関連付けが保持されており、同じものを持つグローバル変数に影響を与えます。このエラーはよく発生します:
ループの後、グローバル変数i
リーリーfor
の値が不可解に変化しました。その理由は、
識別子がfor
が実際にはオブジェクトそのものではなく、Python の識別子の属性ではないためです。オブジェクトですが、オブジェクトの属性は再利用可能な名前空間の一部です。i
i
したがって、同じ名前のループ内で割り当てられる場合、状況は異なります。
の値は、for
リーリーi
ここでの内で割り当てられた値とまったく同じです。その理由は、Python の代入操作が最後の反復中に値オブジェクトを識別子に関連付ける操作であるためです。最初のプログラムに戻ると、値
は単なるインデックスです。変更するのはi
は識別子for
に関連付けられているため、3
は新しいオブジェクトにバインドされています。状況は同じです。i
は値オブジェクト を識別子i
に割り当てるため、割り当てられたi = float(i)
はfloat(i)
の要素オブジェクトではまったくないため、i
は変更されません。i
そして 2 番目のプログラム:data
リーリーdataset
内の
ではなく、
for
識別子に関連付けられたオブジェクトであり、i
はi
の構成要素です。dataset[i]
は変更できます。dataset[i]
dataset
識別子と名前空間については、次の記事を参照してください: Python 名前空間data