Maison > Questions et réponses > le corps du texte
我有一个二维列表,列表中的元素是以字符串
为元素的列表。
由于这些字符串表示的是数字,我想把这些字符串都转换成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
Une variable n'est qu'un pointeur vers un objet
Comprenez-le, puis continuez à lire.
Premier type : lors du parcours, un pointeur nommé i est créé et pointe vers un élément dans data. Lorsque vous exécutez i=float(i), vous créez simplement un nouvel objet float(i) et laissez-le pointer vers lui, c'est tout.
La deuxième méthode est la même.
ringa_lee2017-04-17 17:25:44
Pour être précis, i = float(i)
change la valeur de i
, mais i
n'est qu'une copie de l'élément data
et ne change pas la valeur de data
, tout comme :
>>> a = ["ab", "cd"]
>>> i = a[0]
>>> i = 123
>>> a
['ab', 'cd']
La seconde est que vous opérez directement sur la liste originale :
>>> a[0] = 123
>>> a
[123, 'cd']
PHPz2017-04-17 17:25:44
En python, lors du parcours d'un objet via for, vous ne pouvez pas modifier l'objet parcouru lui-même. C'est une règle générale.
De manière générale, l'élément suivant est obtenu via la méthode next().
Si l'objet de traversée peut être modifié, cela affectera l'ordre des éléments, rendant les résultats de chaque étape suivante incontrôlables.
Pensez à utiliser enumerate pour le modifier.
pour i,v dans enumerate(data):
data[i] = float(v)
À l'heure actuelle, l'objet d'itération est enumerate(data), pas data, il peut donc être modifié.
Pour plus d'informations, veuillez vous référer à la description de l'instruction for dans le manuel officiel de Python :
https://docs.python.org/2/reference/compound_stmts.html#the-for-statement
伊谢尔伦2017-04-17 17:25:44
Dans for
parcours en Python, il n'est généralement pas recommandé (pas impossible) de modifier directement l'objet de parcours lui-même, car cela entraînerait des problèmes similaires aux suivants :
n = [1, 2, 3]
for i in n:
n.append(i)
print(i)
Le programme ci-dessus entrera dans une boucle infinie car la longueur de n
augmente à chaque itération, donc for
ne peut jamais être épuisé, nous utilisons donc généralement une copie de l'objet itération pour parcourir :
n = [1, 2, 3]
for i in n[:]:
n.append(i)
print(i)
De cette façon, la valeur de n
peut être modifiée et le parcours peut être terminé avec succès.
Retournez maintenant au premier programme de votre exemple :
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
En fait, les deux avant et après votre i = float(i)
ne font pas du tout référence au même objet. Ce dernier i
est un élément de data
, et le premier i
est une variable locale dans le. loadCsv
portée. , cela implique un point déraisonnable dans la conception du langage Python, jetons un œil à un programme :
for i in range(3):
pass
print(i)
# 2
C'est-à-dire que l'identifiant i
participant à l'itération n'a pas été recyclé après la sortie de la boucle for
, et conserve l'association avec la dernière valeur de l'itération, ce qui affectera la variable globale de même nom. Cette erreur se produit souvent :
i = 7
for i in range(3):
pass
print(i)
# 2
Après une boucle for
, la valeur de la variable globale i
a changé inexplicablement. La raison en est que i
n'est pas réellement l'objet lui-même, mais l'identifiant de l'objet Python n'est pas un attribut de. l'objet, mais un attribut de l'objet. Fait partie d'un espace de noms réutilisable.
Alors lorsqu'un identifiant for
du même nom est attribué au sein de la boucle i
, la situation est différente :
for i in range(5):
i = 3
print(i)
# 3
La valeur de i
ici est exactement la même que la valeur qui lui est attribuée dans for
La raison en est que l'opération d'affectation en Python est l'opération d'association de l'objet valeur à l'identifiant lors de la dernière itération. , la valeur 3
will est associée à l'identifiant i
, donc i
est lié au nouvel objet. Pour revenir à votre premier programme, c'est le cas : i = float(i)
. Il lie l'objet valeur float(i)
à l'identifiant i
, donc le i
attribué n'est pas du tout l'objet élément de data
, donc dataset
ne sera pas modifié.
Et votre deuxième programme :
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
Le à l'intérieur de for
i
n'est qu'un index. Ce que vous modifiez n'est pas i
, mais l'objet associé à l'identifiant dataset[i]
, et dataset[i]
est un élément composant de dataset
, donc cela peut être modifié data
.
Pour les identifiants et les espaces de noms, vous pouvez lire cet article : Espaces de noms Python