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

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

répondre à tous(4)
迷茫

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.

左手右手慢动作

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']
PHPzhong

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

伊谢尔伦

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 fori 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

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal