Rumah > Soal Jawab > teks badan
我有一个二维列表,列表中的元素是以字符串
为元素的列表。
由于这些字符串表示的是数字,我想把这些字符串都转换成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
这段程序能够成功,又是为什么呢?
迷茫2017-04-17 17:25:44
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.
ringa_lee2017-04-17 17:25:44
Tepatnya, i = float(i)
memang mengubah nilai i
, tetapi i
hanyalah salinan elemen data
dan tidak mengubah nilai data
, sama seperti:
>>> a = ["ab", "cd"]
>>> i = a[0]
>>> i = 123
>>> a
['ab', 'cd']
Yang kedua adalah kerana anda beroperasi terus pada senarai asal:
>>> a[0] = 123
>>> a
[123, 'cd']
PHPz2017-04-17 17:25:44
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 i,v dalam enumerate(data):
data[i] = float(v)
Pada masa ini, objek lelaran ialah enumerate(data), bukan data, jadi ia boleh diubah suai.
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
伊谢尔伦2017-04-17 17:25:44
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:
n = [1, 2, 3]
for i in n:
n.append(i)
print(i)
Atur cara di atas akan memasuki gelung tak terhingga kerana panjang n
bertambah dengan setiap lelaran, jadi for
tidak akan pernah habis, jadi kami biasanya menggunakan salinan objek lelaran untuk melintasi:
n = [1, 2, 3]
for i in n[:]:
n.append(i)
print(i)
Dengan cara ini, nilai n
boleh diubah suai dan traversal dapat diselesaikan dengan jayanya.
Sekarang kembali ke program pertama dalam contoh anda:
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
Malah, dua sebelum dan selepas i = float(i)
anda sama sekali tidak merujuk kepada objek yang sama i
yang terakhir ialah elemen data
dan yang pertama i
ialah pembolehubah setempat dalam. loadCsv
skop , ini melibatkan perkara yang tidak munasabah dalam reka bentuk bahasa Python, mari kita lihat program:
for i in range(3):
pass
print(i)
# 2
Maksudnya, pengecam i
yang mengambil bahagian dalam lelaran belum dikitar semula selepas keluar daripada gelung for
dan mengekalkan perkaitan dengan nilai terakhir lelaran, yang akan menjejaskan pembolehubah global dengan yang sama nama. Ralat ini sering berlaku:
i = 7
for i in range(3):
pass
print(i)
# 2
Selepas gelung for
, nilai pembolehubah global i
berubah secara tidak dapat dijelaskan Sebabnya ialah i
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 gelung i
, situasinya berbeza:
for i in range(5):
i = 3
print(i)
# 3
Nilai i
di sini betul-betul sama dengan nilai yang diberikan kepadanya dalam for
Sebabnya ialah operasi penetapan dalam Python ialah operasi mengaitkan objek nilai dengan pengecam semasa lelaran terakhir , nilai 3
wasiat dikaitkan dengan pengecam i
, jadi i
terikat pada objek baharu anda, ini adalah kesnya: i = float(i)
Ia mengikat objek nilai float(i)
kepada pengecam i
, jadi i
yang ditetapkan bukan objek elemen data
sama sekali, jadi dataset
tidak akan diubah.
Dan program kedua anda:
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
dalam for
i
hanyalah indeks yang anda ubah suai bukan i
, tetapi objek yang dikaitkan dengan pengecam dataset[i]
dan dataset[i]
ialah elemen komponen dataset
, jadi. ia boleh diubah data
.
Untuk pengecam dan ruang nama, anda boleh membaca artikel ini: Ruang nama Python