The article "About python reference" was interesting, so I made a note. In this article,
When I started python, the first thing I stumbled upon was the mysterious explanation that is often seen everywhere: "All python arguments are passed by reference."
There was a passage. As already pointed out in the comments, to be more precise, "all Python arguments are passed by reference", but anyway, it seems that Python doesn't have passing by value! Previously, I wrote an article "Passing by value, passing by reference, and passing by reference" with almost the same theme, where integers and floating point numbers are used. I wrote that the number is passed by value in Python. In fact, it gave a consistent explanation, and in the original article
When a new object itself is assigned to a variable, it will refer to the place where the new object was created instead of the previous reference destination.
That part is the same as what I wrote in the explanation about passing references by value. However, I looked at the comments and I might have written something a little inaccurate, so I investigated it in detail.
Consider the following Python code.
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
This is certainly "passing by reference", not "passing by value". Because if you pass by value, the id (pointer value) should not match as in C ++ below.
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
What if this happens next?
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
In this way, unlike C ++, in Python, if you assign a different value, the id will also change. In other words, the reference destination changes. What about compound assignments like + =?
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
This is the same.
As you can see in the comment of the original article, b + = 2
is actually called b = b + 2
, and a new reference is also assigned.
In other words, in Python, "every time you change the value of an integer, a new object is created in memory and it is assigned, so the id also changes".
In other words, in Python, "once you generate an integer in memory, you can't change it", which is called "** immutable ". The opposite is " mutable **".
Other immutable types include floating point numbers, booleans, strings, tuples, and None, and what is essential in Python is "mutable or not" rather than "passing by value". It will be. I didn't know.
By the way, Java has something similar to the Python example above. Wrapper classes such as String and Integer and 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
In this way, Java Strings and Integers behave like passing by value, even though they are reference types. Let's try decompiling the class file created by compiling the above using 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());
}
}
It's a little hard to see, but both are rewritten by compound assignment to create a new object and change the reference destination. When I didn't know this yet, I said, "I want to return multiple ints and doubles in a method, but it's a hassle to create a class just for that, and ints and doubles can only be passed by value. I thought, "Isn't it possible to pass it as an argument?"
To summarize the above, we conclude that ** immutable types do not allow you to change the value of an object once created, so even passing by reference will behave substantially the same as passing by value **. Become. Excuse me.
Recommended Posts