python中for语句中对当前遍历对象赋值的问题?
PHP中文网
PHP中文网 2017-04-17 17:23:44
0
4
971

我有一个二维列表,列表中的元素是以字符串为元素的列表。
由于这些字符串表示的是数字,我想把这些字符串都转换成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

这段程序能够成功,又是为什么呢?

PHP中文网
PHP中文网

认证高级PHP讲师

全員に返信(4)
迷茫

変数はオブジェクトへの単なるポインタです

それを理解してから読み続けてください。

最初のタイプ: トラバーサル中に、i という名前のポインターが作成され、データ内の要素を指します。 i=float(i) を実行するときは、新しいオブジェクト float(i) を作成し、i にそれをポイントさせるだけです。

2番目と同様。

いいねを押す +0
左手右手慢动作

正確に言うと、i = float(i)i の値を変更しますが、idata 要素の単なるコピーであり、次のように data の値を変更しません。 リーリー

2 つ目は、元のリストを直接操作するためです:

リーリー

いいねを押す +0
PHPzhong

Python では、for を介してオブジェクトを走査するとき、走査されたオブジェクト自体を変更することはできません。これは一般的な規則です。
一般に、次の要素は next() メソッドを通じて取得されます。
トラバーサル オブジェクトの変更が許可されている場合、要素の順序に影響し、次の各ステップの結果が制御不能になります。
enumerate を使用して変更することを検討してください。

for i,v in enumerate(data):

リーリー

この時点では、反復オブジェクトは data ではなく enumerate(data) なので、変更できます。

追加情報については、公式 Python マニュアルの for ステートメントの説明を参照してください:
https://docs.python.org/2/reference/compound_stmts.html#the-for-statement

いいねを押す +0
伊谢尔伦

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 識別子に関連付けられたオブジェクトであり、ii の構成要素です。 dataset[i]は変更できます。 dataset[i] dataset識別子と名前空間については、次の記事を参照してください: Python 名前空間data

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート