Un peu plus sur les références ~ Prenant Python et Java comme exemples ~

introduction

Notez que l'article "A propos de la référence python" était intéressant. Dans cet article,

Quand j'ai commencé python, la première chose sur laquelle je suis tombé par hasard a été la mystérieuse explication que l'on voit souvent partout: "Tous les arguments python sont passés par référence."

Il y avait un passage. Comme déjà souligné dans les commentaires, pour être plus précis, "tous les arguments Python sont passés par référence", mais de toute façon, il semble qu'il n'y ait pas de passage par valeur en Python! J'écrivais un article "Passer par valeur, passer par référence, passer par référence" avec presque le même thème, où entiers et virgules flottantes J'ai écrit que le nombre est passé par valeur en Python. En fait, il a donné une explication cohérente, et l'article original

Lorsqu'un nouvel objet lui-même est affecté à une variable, il fera référence à l'endroit où le nouvel objet a été créé au lieu de la destination de référence précédente.

Cette partie est la même que ce que j'ai écrit dans l'explication sur le passage des références par valeur. Cependant, j'ai regardé les commentaires et j'ai peut-être écrit quelque chose d'un peu inexact, alors je l'ai étudié en détail.

Comportement des nombres entiers en Python et C ++

Considérez le code Python suivant.

ex1.py


a = 1
b = a
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)))
a : value = 1	id = 4360526320
b : value = 1	id = 4360526320

Il s'agit certainement de "passer par référence", pas de "passer par valeur". Parce que si vous passez par valeur, id (valeur du pointeur) ne doit pas correspondre comme le C ++ suivant.

ex1.cpp


#include <iostream>

int main(){
    int a = 1;
    int b = a;
    std::cout << "a : value = " << a << "\tid = " << &a << "\n";
    std::cout << "b : value = " << b << "\tid = " << &b << "\n";
    return 0;    
}
a : value = 1	id = 0x7fff50360ae8
b : value = 1	id = 0x7fff50360ae4

Et si cela arrivait ensuite?

ex2.py


a = 1
b = a
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)) + "\n")

b = 2
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)))
a : value = 1	id = 4348889584
b : value = 1	id = 4348889584

a : value = 1	id = 4348889584
b : value = 2	id = 4348889616

ex2.cpp


#include <iostream>

int main(){
    int a = 1;
    int b = a;
    std::cout << "a : value = " << a << "\tid = " << &a << "\n";
    std::cout << "b : value = " << b << "\tid = " << &b << "\n\n";
    
    b = 2;
    std::cout << "a : value = " << a << "\tid = " << &a << "\n";
    std::cout << "b : value = " << b << "\tid = " << &b << "\n";
    return 0;
}
a : value = 1	id = 0x7fff561cdae8
b : value = 1	id = 0x7fff561cdae4

a : value = 1	id = 0x7fff561cdae8
b : value = 2	id = 0x7fff561cdae4

De cette façon, contrairement au C ++, en Python, si vous attribuez une valeur différente, l'id changera également. En d'autres termes, la destination de référence change. Qu'en est-il des affectations composées comme + =?

ex3.py


a = 1
b = a
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)) + "\n")

b += 2
print("a : value = " + str(a) + "\tid = " + str(id(a)))
print("b : value = " + str(b) + "\tid = " + str(id(b)))
a : value = 1	id = 4507830768
b : value = 1	id = 4507830768

a : value = 1	id = 4507830768
b : value = 3	id = 4507830832

C'est pareil. Comme vous pouvez le voir dans le commentaire de l'article original, «b + = 2» est en fait appelé «b = b + 2», et une nouvelle référence est également attribuée. En d'autres termes, en Python, "Chaque fois que vous modifiez la valeur d'un entier, un nouvel objet est créé dans la mémoire et il est attribué, donc l'id change également." En d'autres termes, en Python, «une fois que vous générez un entier en mémoire, vous ne pouvez pas le changer», ce qui s'appelle «** immuable ». Le contraire est " mutable **". D'autres types immuables incluent les nombres à virgule flottante, les bourians, les chaînes, les taples et None, et ce qui est essentiel en Python est "mutable ou non" plutôt que "passer par valeur". Ce sera. Je ne savais pas.

Chaîne Java et classe wrapper

À propos, Java a quelque chose de similaire à l'exemple Python ci-dessus. Classes wrapper telles que String et Integer et Double.

Ex1.java


class Ex1{
    public static void main(String[] args){
        String s1 = "foo";
        String s2 = s1;
        System.out.println("s1 : " + s1);
        System.out.println("s2 : " + s2 + "\n");
        
        s2 += "bar";
        System.out.println("s1 : " + s1);
        System.out.println("s2 : " + s2 + "\n");

        Integer i1 = 1;
        Integer i2 = i1;
        System.out.println("i1 : " + i1);
        System.out.println("i2 : " + i2 + "\n");
        
        i2 += 2;
        System.out.println("i1 : " + i1);
        System.out.println("i2 : " + i2);
    }
}
s1 : foo
s2 : foo

s1 : foo
s2 : foobar

i1 : 1
i2 : 1

i1 : 1
i2 : 3

De cette façon, les chaînes Java et les entiers se comportent comme des valeurs de passage, bien qu'il s'agisse de types référence. Essayons de décompiler le fichier de classe créé en compilant ce qui précède en utilisant jad.

Ex1.jad


// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   Ex1.java

import java.io.PrintStream;

class Ex1
{

    Ex1()
    {
    }

    public static void main(String args[])
    {
        String s = "foo";
        String s1 = s;
        System.out.println((new StringBuilder()).append("s1 : ").append(s).toString());
        System.out.println((new StringBuilder()).append("s2 : ").append(s1).append("\n").toString());
        s1 = (new StringBuilder()).append(s1).append("bar").toString();
        System.out.println((new StringBuilder()).append("s1 : ").append(s).toString());
        System.out.println((new StringBuilder()).append("s2 : ").append(s1).append("\n").toString());
        Integer integer = Integer.valueOf(1);
        Integer integer1 = integer;
        System.out.println((new StringBuilder()).append("i1 : ").append(integer).toString());
        System.out.println((new StringBuilder()).append("i2 : ").append(integer1).append("\n").toString());
        integer1 = Integer.valueOf(integer1.intValue() + 2);
        System.out.println((new StringBuilder()).append("i1 : ").append(integer).toString());
        System.out.println((new StringBuilder()).append("i2 : ").append(integer1).toString());
    }
}

C'est un peu difficile à voir, mais les deux sont réécrits en tant qu'affectations composées pour créer un nouvel objet et modifier la référence. Quand je ne le savais pas encore, j'ai dit: «Je veux renvoyer plusieurs entiers et doubles dans une méthode, mais il est difficile de créer une classe juste pour cela, et les entiers et les doubles ne peuvent être passés que par valeur. J'ai pensé: "N'est-il pas possible de le faire passer pour un argument?"

Résumé

Pour résumer ce qui précède, nous concluons que ** les types immuables ne vous permettent pas de changer la valeur d'un objet une fois créé, donc même le passage par référence se comportera sensiblement comme le passage par valeur **. Devenir. Excusez-moi.

Recommended Posts

Un peu plus sur les références ~ Prenant Python et Java comme exemples ~
Un peu plus sur le FIFO
[Python] Chapitre 01-03 À propos de Python (Ecrire et exécuter un programme à l'aide de PyCharm)
À propos de Python, à partir et à l'importation, comme
Un programmeur Java a étudié Python. (À propos du type)
Un peu plus de détails sur la notation d'inclusion de python
Une histoire sur Python pop and append
Gestion des exceptions Python un peu plus pratique
Un programmeur Java a étudié Python. (À propos des fonctions (méthodes))
Un programmeur Java a étudié Python. (À propos des décorateurs)
J'ai écrit une classe en Python3 et Java
Pourquoi je suis une boutique Java et démarre Python
Créer une carte Web en utilisant Python et GDAL
Une histoire sur la modification de Python et l'ajout de fonctions
Essayez de créer un fichier compressé en utilisant Python et zlib
Implémentation d'un générateur en utilisant Python> link> yield et next ()> yield
(Pour moi) Flask_2 (liste et pour, étend, et un peu plus)
Ce que j'ai appris sur l'IA / l'apprentissage automatique avec Python (4)
Résolution avec Ruby, Perl, Java et Python AtCoder ATC 002 A
Tirez en accéléré à partir d'une caméra PC en utilisant Python, OpenCV
J'ai créé Chatbot en utilisant l'API LINE Messaging et Python
À propos des objets et des classes Python
À propos des variables et des objets Python
J'ai comparé Java et Python!
À propos de Python, len () et randint ()
À propos de la date et du fuseau horaire Python
Mémorandum sur la corrélation [Python]
Un mémorandum sur le simulacre de Python
À propos de Python et des expressions régulières
À propos des opérations Python et OS
Python # À propos de la référence et de la copie
À propos de Python sort () et reverse ()
Une note sur [python] __debug__
Automatisation d'une recherche sur des informations géographiques telles que le réseau de magasins à l'aide de Python et de l'API Web
[Python] Comment récupérer un fichier html local et le générer au format CSV à l'aide de Beautiful Soup
Créez un classement de jeu sur le cloud Alibaba en utilisant Python et Redis
Traitez le résultat de l'exécution de Splunk en utilisant Python et enregistrez-le dans un fichier
Créez un lot planifié simple à l'aide de l'image Python de Docker et de parse-crontab
Après avoir fait des recherches sur la bibliothèque Python, j'ai un peu compris egg.info.
[Python] J'ai écrit une API REST en utilisant AWS API Gateway et Lambda.
J'ai créé Chatbot en utilisant l'API LINE Messaging et Python (2) ~ Server ~
Construction de l'environnement LaTeX et R (un peu Python) avec SublimeText3 (Windows)
Python a + = b et a = a + b sont différents
Avantages et exemples d'utilisation de Rabbit Mq
Comparaison de la grammaire de base entre Java et Python
J'ai fait un Line-bot avec Python!
Créer une interface graphique python à l'aide de tkinter
[Java] Un petit comportement de scission mystérieux
Dessiner une courbe Silverstone en utilisant Python
À propos de Python dict et des fonctions triées
À propos de Python et Cython dtype
À propos de Python Pickle (cPickle) et Marshal
[Python] À propos des classes Executor et Future
Utilisez Blender comme module Python
Clustering et visualisation à l'aide de Python et CytoScape
[Python] renvoie A [ou / et] B
L'histoire de l'utilisation de la réduction de Python
Lancer le script Python en service
Une note sur mock (bibliothèque fictive Python)