我有一个二维列表,列表中的元素是以字符串
为元素的列表。
由于这些字符串表示的是数字,我想把这些字符串都转换成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
这段程序能够成功,又是为什么呢?
Pembolehubah hanyalah penunjuk kepada objek
Fahami, kemudian teruskan membaca.
Jenis pertama: Semasa traversal, penunjuk bernama i dicipta dan menunjuk ke elemen dalam data. Apabila anda melaksanakan i=float(i), anda hanya mencipta objek baru float(i) dan biarkan saya menunjuk kepadanya, itu sahaja.
Kaedah kedua adalah sama.
Tepatnya,
i = float(i)
memang mengubah nilaii
, tetapii
hanyalah salinan elemendata
dan tidak mengubah nilaidata
, sama seperti:Yang kedua adalah kerana anda beroperasi terus pada senarai asal:
Dalam python, apabila melintasi objek melalui untuk, anda tidak boleh mengubah suai objek yang dilalui itu sendiri. Ini adalah peraturan umum.
Secara umumnya, elemen seterusnya diperoleh melalui kaedah next().
Jika objek traversal dibenarkan untuk diubah suai, ia akan menjejaskan susunan elemen, menjadikan keputusan setiap langkah seterusnya tidak dapat dikawal.
Pertimbangkan untuk menggunakan enumerate untuk mengubah suainya.
Untuk mendapatkan maklumat tambahan, sila rujuk huraian pernyataan for dalam manual Python rasmi:
https://docs.python.org/2/reference/compound_stmts.html#the-for-statement
Dalam
for
traversal dalam Python, biasanya tidak disyorkan (tidak mustahil) untuk mengubah suai secara langsung objek traversal itu sendiri, kerana ini akan menyebabkan masalah yang serupa dengan yang berikut:Atur cara di atas akan memasuki gelung tak terhingga kerana panjang
n
bertambah dengan setiap lelaran, jadifor
tidak akan pernah habis, jadi kami biasanya menggunakan salinan objek lelaran untuk melintasi:Dengan cara ini, nilai
n
boleh diubah suai dan traversal dapat diselesaikan dengan jayanya.Sekarang kembali ke program pertama dalam contoh anda:
Malah, dua sebelum dan selepas
i = float(i)
anda sama sekali tidak merujuk kepada objek yang samai
yang terakhir ialah elemendata
dan yang pertamai
ialah pembolehubah setempat dalam.loadCsv
skop , ini melibatkan perkara yang tidak munasabah dalam reka bentuk bahasa Python, mari kita lihat program:Maksudnya, pengecam
i
yang mengambil bahagian dalam lelaran belum dikitar semula selepas keluar daripada gelungfor
dan mengekalkan perkaitan dengan nilai terakhir lelaran, yang akan menjejaskan pembolehubah global dengan yang sama nama. Ralat ini sering berlaku:Selepas gelung
for
, nilai pembolehubah globali
berubah secara tidak dapat dijelaskan Sebabnya ialahi
sebenarnya bukan objek itu sendiri, tetapi pengecam objek itu bukan atribut objek, tetapi atribut objek adalah sebahagian daripada ruang nama yang boleh digunakan semula.Jadi apabila pengecam
for
dengan nama yang sama diberikan dalam gelungi
, situasinya berbeza:Nilai
i
di sini betul-betul sama dengan nilai yang diberikan kepadanya dalamfor
Sebabnya ialah operasi penetapan dalam Python ialah operasi mengaitkan objek nilai dengan pengecam semasa lelaran terakhir , nilai3
wasiat dikaitkan dengan pengecami
, jadii
terikat pada objek baharu anda, ini adalah kesnya:i = float(i)
Ia mengikat objek nilaifloat(i)
kepada pengecami
, jadii
yang ditetapkan bukan objek elemendata
sama sekali, jadidataset
tidak akan diubah.Dan program kedua anda:
dalam
for
i
hanyalah indeks yang anda ubah suai bukani
, tetapi objek yang dikaitkan dengan pengecamdataset[i]
dandataset[i]
ialah elemen komponendataset
, jadi. ia boleh diubahdata
.Untuk pengecam dan ruang nama, anda boleh membaca artikel ini: Ruang nama Python