Quand les fonctions python affectent-elles les arguments de l'appelant?

Qu'est-ce qui est passé dans l'argument de la fonction python? Si vous ne le savez pas, vous détruirez l'objet d'origine. Cette fois, c'est une expérience pour le confirmer. La version de python est la 3.4.3.

Copiez le tableau

En python, la modification des arguments passés dans une fonction n'affecte pas les arguments d'origine.

mystr = "test"
myint = 100

def modify_str_and_int(mystr, myint):
    mystr = "after"
    myint = 200

modify_str_and_int(mystr, myint)
print("mystr = %s" % mystr)
print("myint = %s" % myint)

# =>
# mystr = test
# myint = 100

Prendre un tableau comme argument affecte également le tableau appelant. Par conséquent, il n'est pas nécessaire de renvoyer le tableau traité comme valeur de retour.

mylist = ["foo","bar",100]
def modify_list(mylist):
    mylist.append("new")

print(mylist)
modify_list(mylist)
print(mylist)

['foo', 'bar', 100]
['foo', 'bar', 100, 'new']

Cependant, il arrive parfois que vous ne souhaitiez pas le modifier. Par exemple, lors de la réutilisation du tableau appelant. Dans ce cas, définissez une nouvelle variable dans la fonction et déplacez la valeur.

mylist = ["foo","bar",100]
def modify_list(mylist):
    new_list = mylist
    new_list.append("new")
    return new_list

print(mylist)
modify_list(mylist)
print(mylist)

# =>
# ['foo', 'bar', 100]
# ['foo', 'bar', 100, 'new']

La valeur d'origine a été réécrite. C'est parce que vous passez une référence à nouvelle_liste, pas une copie de la valeur. Ainsi, les deux variables new_list et mylist pointent vers le même objet de liste. Cela peut être confirmé par id.

mylist = ["foo"]
new_list = mylist

print(id(mylist))
print(id(new_list))
print(id(mylist) == id(new_list))

# =>
# 4528474888
# 4528474888
# True

Créons donc un nouvel objet liste avec la même valeur que mylist. La liste de fonctions intégrée est une fonction de conversion d'un type de séquence en liste, mais il est également possible de créer un nouvel objet liste à partir de la liste.

mylist = ["foo"]
new_list = list(mylist)

print(id(mylist))
print(id(new_list))
print(id(mylist) == id(new_list))

# =>
# 4313320328
# 4313327816
# False

S'il est utilisé dans une fonction de la même manière, il n'affectera pas le tableau d'origine.

mylist = ["foo","bar",100]
def modify_list(mylist):
    new_list = list(mylist)
    new_list.append("new")
    return new_list

print(mylist)
new_list = modify_list(mylist)
print(mylist)
print(new_list)

# =>
# ['foo', 'bar', 100]
# ['foo', 'bar', 100]
# ['foo', 'bar', 100, 'new']

Int et str sont également passés par référence

Dans le premier exemple que j'ai vu, la modification de int et str dans la fonction n'affectait pas l'objet d'origine. La raison pour laquelle il a affecté le tableau était parce qu'il pointait vers le même objet. En d'autres termes, les identifiants des objets étaient les mêmes. Alors, l'id est-il différent pour int et str?

mystr = "test"
myint = 100

def modify_str_and_int(mystr, myint):
    print("mystr = %s" % id(mystr))
    print("myint = %s" % id(myint))

print("mystr = %s" % id(mystr))
print("myint = %s" % id(myint))
modify_str_and_int(mystr, myint)

# =>
# mystr = 4308535648
# myint = 4305807456
# mystr = 4308535648
# myint = 4305807456

cette? Les deux sont identiques. Cela devrait également affecter la valeur d'origine. Essayons encore.

mystr = "test"
myint = 100

def modify_str_and_int(mystr, myint):
    mystr = "after"
    print("mystr = %s" % id(mystr))
    print("myint = %s" % id(myint))

print("mystr = %s" % id(mystr))
print("myint = %s" % id(myint))
modify_str_and_int(mystr, myint)

# =>
# mystr = 4557928800
# myint = 4555208800
# mystr = 4557705768
# myint = 4555208800

cette! ?? Cette fois, seul mystr a changé d'id. C'est un problème de portée. Puisque python est tous les objets, l'id de l'objet est passé tel qu'il est dans l'argument. Si la même variable est nouvellement définie dans la fonction, le comportement changera selon le tableau et int ou str. Cette fois, l'id de str a changé. Le critère est de savoir si l'objet est mutable (variable) ou immuable (immuable). S'il est immuable, un objet avec la même valeur est créé, donc l'id a changé.

Vous pouvez voir que la même valeur d'identifiant est transmise à la variable même si elle n'est pas à l'intérieur de la fonction. Une différence est que si vous utilisez le même nom d'argument, vous pointerez vers vous-même. Dans la fonction, la première est traitée comme une nouvelle variable.

mystr = "test"
myint = 100
mylist = ['foo', 'bar']

new_str = mystr
new_int = myint
new_list = mylist

print(id(new_str) == id(mystr))
print(id(new_int) == id(myint))
print(id(new_list) == id(mylist))
# =>
# True
# True
# True

def display_outer():
    print("mystr = %s" % mystr)
    print("myint = %s" % myint)
    print("mylist = %s" % mylist)

display_outer()
# =>
# mystr = test
# myint = 100
# mylist = ['foo', 'bar']

Les fonctions peuvent faire référence à des variables externes

Il s'avère que la valeur id est transmise telle quelle dans l'argument. Cela signifie qu'il est possible de faire référence à la variable externe à l'intérieur de la fonction.

mystr = "test"
myint = 100
mylist = ['foo', 'bar']

def display_outer():
    print("mystr = %s" % mystr)
    print("myint = %s" % myint)
    print("mylist = %s" % mylist)

display_outer()
# =>
# mystr = test
# myint = 100
# mylist = ['foo', 'bar']

Recommended Posts

Quand les fonctions python affectent-elles les arguments de l'appelant?
Arguments de mots-clés pour les fonctions Python
Vérifiez le comportement lors de l'attribution de Python
Que faire lorsque le type de valeur est ambigu en Python?
Fonctions Python
Comment passer des arguments lors de l'appel d'un script python depuis Blender sur la ligne de commande
# Bases de Python (fonctions)
[Débutant] Fonctions Python
Fonctions Python faciles à utiliser
bases de python: fonctions
Quand les arguments par défaut seront-ils liés en python? Lorsque les variables sont liées dans l'évaluation différée de la fermeture.
Que faire lorsque l'imitation est intégrée à Python
[Python of Hikari-] Chapitre 06-04 Fonctions (arguments et valeurs de retour 3)
Recevez le formulaire en Python et faites diverses choses
Paramètres initiaux lors de l'utilisation de l'API foursquare avec python
(◎◎) {Laissons Python faire les choses ennuyeuses) ......... (Hé? Laissons Python faire les devoirs} (゜) (゜)
python Spécifie la fonction à exécuter lorsque le programme se termine
Que faire lorsque "impossible d'importer le nom xxx" [Python]
À propos de l'option --enable-shared lors de la construction de Python sous Linux
[Python of Hikari-] Chapitre 06-03 Fonctions (arguments et valeurs de retour 2)
Pour faire l'équivalent de Ruby ObjectSpace._id2ref en Python
Combien connaissez-vous les bases de Python?
Je veux faire quelque chose avec Python à la fin
Pas étonnamment connu! ?? Qu'en est-il des arguments de fonction intégrés? De quelle école êtes-vous? [Python]
Élément de note Python efficace 20 Utilisez Aucun et la chaîne de documentation lors de la spécification d'arguments par défaut dynamiques