Explication détaillée des objets mutables et des objets immuables en Python

零下一度
Libérer: 2017-06-30 14:30:40
original
1897 Les gens l'ont consulté

Objets mutables et objets immuables en Python

Que sont les objets mutables/immuables

  • Objets immuables vers lesquels pointent les objets La valeur en mémoire ne peut pas être modifié. Lorsqu'une variable est modifiée, puisque la valeur à laquelle elle fait référence ne peut pas être modifiée, cela équivaut à copier la valeur d'origine puis à la modifier. Cela ouvrira une nouvelle adresse et la variable pointera vers cette nouvelle adresse.

  • Objet mutable, la valeur dans la mémoire pointée par l'objet peut être modifiée. Après la modification d'une variable (référence pour être précis), la valeur à laquelle elle fait référence est en fait modifiée directement. Il n'y a pas de comportement de copie et aucune nouvelle adresse sortante n'est ouverte. En termes simples, elle est modifiée sur place. . .

En Python, le type numérique (int et float), la chaîne str et le tuple tuple sont tous des types immuables. Les listes, dictionnaires et ensembles sont des types de variables.

Il est plus intuitif de regarder le code. Regardons d'abord des exemples d'objets immuables

Objets immuables

Laissez-moi d'abord vous expliquer une chose : is consiste à déterminer si les identifiants de deux objets sont les mêmes, tandis que == détermine le contenu. Sont-ils identiques.

a = 2b = 2c = a + 0 c += 0print(id(a), id(b), id(2))  # id都相同print(c is b) #True
Copier après la connexion

Regardons la chaîne

astr = 'good'bstr = 'good'cstr = astr + ''print(cstr is bstr) # Trueprint(id(astr), id(bstr), id('good'))  # 三个id相同
Copier après la connexion

qui a le même résultat que le type numérique. Si c'est la situation suivante, la variable n'est plus good

astr = 'good'print(id(astr))
astr += 'aa'print(id(astr)) # id和上面的不一样
Copier après la connexion

après modification Puisqu'il s'agit d'un objet immuable, la valeur de la mémoire correspondant à. la variable ne peut pas être modifiée. Lorsqu'une variable doit être modifiée, la valeur d'origine est effectivement copiée puis modifiée, une nouvelle adresse est ouverte et astr pointe vers cette nouvelle adresse (donc l'identifiant de l'astr précédent et de l'astr précédent est différent de la valeur correspondante). l'astr d'origine est différent car si un autre objet pointe vers lui, il sera récupéré. C'est la même chose pour les types int et float.

Regardez le tuple

add = (1, 2, 3)
aee = (1, 2, 3)print(id(add), id(aee), id((1, 2, 3)))  # id各不相同aee = (1, 2, 3)print(id(aee))
aee += () # 加空元组print(id(aee))  # id变了!print(aee)  #(1 ,2,3)
Copier après la connexion

Bien qu'il semble que ce soit le cas (1 ,2, 3), il devrait être cohérent avec ce qui précède. Est-ce un objet mutable ? Regardez à nouveau

add = (1, 2, 3)
aee = add 
print(id(aee), id(add)) # 这两个id一样aee += (4, 5, 6)print(id(aee)) # aee的id变了!print(add) # add还是(1, 2, 3)没有变
Copier après la connexion

est cohérent avec le type numérique et le type str. S'il s'agit d'un objet mutable add = aee, il est certain qu'ils pointent vers la même adresse (même id). Mais il ne s’agit pas de références différentes au même objet, car si c’est le cas, les changements dans aee entraîneront des changements dans add, ce qui n’est pas le cas dans tuple. Le tuple est donc un objet immuable, mais il est légèrement différent des types str et numériques. L'immuabilité des tuples signifie généralement que les valeurs qui y sont stockées ne peuvent pas être modifiées (Dans certains cas particuliers, comme une liste stockée dans un tuple, les éléments de la liste peuvent être modifiés. Mais en fait, le tuple n'a pas été modifié).

Pour str、int、float tant qu'ils ont le même type et la même valeur, alors leurs identifiants sont les mêmes. (Pourquoi dites-vous qu'ils sont du même type ?)

a = 2.0b = 2print(a is b)  # False, 一个int一个float,类型都不同
Copier après la connexion

2 et 2.0 ne sont pas à la même adresse.

Exemples d'objets mutables

lis = [1, 2, 3]
lis2 = [1, 2, 3]# 虽然它们的内容一样,但是它们指向的是不同的内存地址print(lis is lis2)print(id(lis), id(lis2), id([1, 2, 3]))  # 三个id都不同
Copier après la connexion

Regardez l'affectation

alist = [1, 2, 3]# alist实际上是对对象的引用,blist = alist即引用的传递,现在两个引用都指向了同一个对象(地址)blist = alistprint(id(alist), id(blist))  # id一样# 所以其中一个变化,会影响到另外一个blist.append(4)print(alist)  # 改变blist, alist也变成了[1 ,2 ,3 4]print(id(alist), id(blist))  # id一样,和上面值没有改变时候的id也一样
Copier après la connexion

blist = alist Cette phrase. alist est en fait une référence à l'objet, blist = alist est le transfert de la référence, et maintenant les deux références pointent vers le même objet (adresse). Ainsi, les changements dans l’un affecteront l’autre.

Regardez set

abb = {1, 2, 3}
acc = abbprint(id(abb), id(acc))
acc.add(4)print(abb)  # {1, 2, 3, 4} print(id(abb), id(acc)) # 相等
Copier après la connexion

qui est cohérent avec l'exemple de la liste ci-dessus.

Puisque l'objet pointé d'un objet variable peut être modifié, il n'est pas nécessaire d'en faire une copie puis de le modifier. Il peut être modifié directement sur place, donc aucune nouvelle mémoire ne sera ouverte, ni l'identifiant. reste inchangé avant et après le changement.

Bien sûr, ce n'est pas le cas pour les objets immuables. Vous pouvez le comparer avec ceci

abc = 3dd = abc
dd = 43print(abc)  # 3,并不随dd的改变而改变
Copier après la connexion

Mais s'il s'agit d'une copie, c'est simplement une copie. le contenu et le transmettre. Et non cité. Ceci est particulièrement utile lorsque vous souhaitez utiliser les valeurs d'une liste sans modifier la liste d'origine.

blist = alist[:]  # or alist.copy()print(alist is blist)  # Falseblist.append(4)print(alist)  # 还是[1,2 ,3]没有变化
Copier après la connexion

en tant que paramètre de fonction

En tant que paramètre de fonction, c'est la même chose. Les types variables transmettent des références, tandis que les types immuables transmettent du contenu.

test_list = [1, 2, 3, 4]
test_str = 'HAHA'def change(alist):
    alist.append(5)def not_change(astr):
    astr.lower()


change(test_list)
not_change(test_str)print(test_list)  # 改变了原来的值print(test_str)  # 没有变
Copier après la connexion

Bien sûr, si vous ne souhaitez pas modifier la valeur de la liste d'origine, les paramètres peuvent être passés dans une copie de la variable de colonne. alsit[:]

Exemple intéressant

En regardant un autre exemple intéressant, nous savons que cette liste peut être ajoutée à une liste en utilisant +.

a1 = [1, 2, 3]
a2 = a1print(id(a1), id(a2))# 实际上是a2指向了新的对象,id已经改变。# 所以现在a2、a1并不是同一对象的两个引用了,a2变化a1不会改变a2 = a2 + [4] # 这个等式中,右边的a2还是和a1的id一样的,一旦赋值成功,a2就指向新的对象print(id(1), id(a2))  # 不等,a2的id变化了print(a1) # [1, 2, 3]没有变
Copier après la connexion

Si vous écrivez comme ça

a1 = [1, 2, 3]
a2 = a1print(id(a1), id(a2))
a2 += [4]  # 相当于调用了a2.extend([4]),原地改变并没有新的对象产生print(id(1), id(a2))  # 相等,a2的id没有变化print(a1)
Copier après la connexion

La différence est que a2 += [4] équivaut à appeler a2.extend([4])It équivaut à changer de place et aucun nouvel objet n'est généré.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal