我有一个二维列表,列表中的元素是以字符串
为元素的列表。
由于这些字符串表示的是数字,我想把这些字符串都转换成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
这段程序能够成功,又是为什么呢?
A variable is just a pointer to an object
Understand it, and then continue reading.
First type: During traversal, a pointer named i is created and points to an element in data. When you execute i=float(i), you just create a new object float(i) and let i point to it, that's all.
The second one is the same.
To be precise, the value of
i = float(i)
的确改变了i
的值,但i
只是data
元素的一份copy,并没有改变data
is like:The second is because you operate directly on the original list:
In python, when traversing an object through for, you cannot modify the traversed object itself. This is a general rule.
Generally speaking, the next element is obtained through the next() method.
If the traversal object is allowed to be modified, it will affect the order of elements, making the results of each next step uncontrollable.
Consider using enumerate to modify it.
For additional information, please refer to the description of the for statement in the official Python manual:
https://docs.python.org/2/reference/compound_stmts.html#the-for-statement
In
for
traversal in Python, it is usually not recommended (not impossible) to directly modify the traversal object itself, because this will cause problems similar to the following:for
遍历通常不建议(不是不能)直接修改遍历对象本身,因为这样就会出现类似如下的问题:上段程序会进入无限死循环,因为
n
在每次迭代时,长度都会增加,因此for
永远不可能穷尽,所以我们通常会使用迭代对象的副本进行遍历:这样就可以修改
n
的值,也可以顺利完成遍历。现在回到你的例子的第一段程序中:
事实上,你的
i = float(i)
前后两个指代的根本不是同一个对象,后一个i
是data
的元素,前一个i
则是loadCsv
作用域内的局部变量,这里涉及到 Python 语言设计中的一个不合理的地方,来看一段程序:也就是说参与迭代的标识符
i
在退出for
循环之后,仍然没有被回收,并且保留着与迭代最后一个值之间的关联,这对同名的全局变量会造成影响,时常会出现这样的错误:一个
for
循环之后,全局变量i
的值尽然莫名其妙的变了,原因在于i
其实并非对象本身,而是对象的标识符,Python 的标识符并非对象的属性,而是可以复用的命名空间的一部分。因此当
for
循环内有同名的i
标识符被赋值时,情况就又不一样了:这里
i
的值完全等同于for
内给它的赋值,原因在于 Python 中的赋值操作,就是将值对象与标识符关联的操作,最后一次迭代时,数值3
会被关联到标识符i
,因此i
就被绑定到新的对象上了,回到你的第一段程序,情况也就是如此:i = float(i)
是将值对象float(i)
绑定到标识符i
,因此赋值后的i
压根不是data
的元素对象,因此不会更改dataset
。而你的第二段程序:
The above program will enter an infinite loop, because the length offor
内的i
只是个索引,你修改的不是i
,而是dataset[i]
标识符关联的对象 ,而dataset[i]
则是dataset
的组成元素,因此可以更改data
rrreeen
will increase with each iteration, sofor
can never be exhausted, so we usually use the iteration object Copy to traverse:rrreee
In this way, the value ofn
can be modified and the traversal can be completed smoothly. 🎜 🎜Now go back to the first program in your example: 🎜 rrreee 🎜In fact, youri = float(i)
does not refer to the same object at all. The latteri
isdata
element, the previousi
is a local variable within the scope ofloadCsv
. This involves an unreasonable point in Python language design. Let’s take a look at a program: 🎜 rrreee 🎜That is to say, the identifieri
participating in the iteration has not been recycled after exiting thefor
loop, and retains the association with the last value of the iteration. This is Global variables with the same name will have an impact, and errors like this often occur: 🎜 rrreee 🎜After afor
loop, the value of the global variablei
changed inexplicably. The reason is thati
is not actually the object itself, but the object's Identifiers in Python are not attributes of objects, but part of a reusable namespace. 🎜 🎜So when thei
identifier with the same name is assigned within thefor
loop, the situation is different: 🎜 rrreee 🎜The value ofi
here is completely equivalent to the value assigned to it infor
. The reason is that the assignment operation in Python is the operation of associating the value object with the identifier. The last time When iterating, the value3
will be associated with the identifieri
, soi
is bound to the new object, back to you This is the case in the first program:i = float(i)
binds the value objectfloat(i)
to the identifieri
code>, so the assignedi
is not the element object ofdata
at all, sodataset
will not be changed.And your second program: 🎜 rrreee 🎜
i
infor
is just an index. What you modify is noti
, but thedataset[i]
identifier. The object associated with the symbol, anddataset[i]
is a component element ofdataset
, sodata
can be changed. 🎜 🎜For identifiers and namespaces, you can read this article: Python namespaces🎜