読者です 読者をやめる 読者になる 読者になる

@ゲー単走部

ローグライク雑記。変愚蛮怒、DCSSなど。

オブジェクトIDと関数への引数渡し

プログラミング Python Java
import java.util.List;
import java.util.ArrayList;

public class Main {
    public static void func(List<Integer> array) {
        array.set(0, 10);
    }
    
    public static void func2(List<Integer> array) {
        array = new ArrayList<Integer>();
        array.add(10); array.add(2);
    }
    
    
    public static void main(String[] args) {
        List<Integer> p1 = new ArrayList<Integer>(); p1.add(1); p1.add(2);
        List<Integer> p2 = new ArrayList<Integer>(); p2.add(1); p2.add(2);
        
        func(p1); func2(p2);
        
        for (int n1: p1) System.out.print(n1 + ",");
        System.out.println("");
        for (int n2: p2) System.out.print(n2 + ",");
    }
}

// 出力結果
// 10,2,
// 1,2,

これは納得の挙動。
p2にはリスト[1, 2]への参照値が代入されていて、これがfunc2に渡される。
func2の仮引数arrayにp2に代入されていた[1, 2]への参照値がコピーされる。
新しいリストを作成し、その参照値をarrayに代入することで、arrayがp2を指さなくなる。
よって、arrayの指すリストをいくら弄ろうと、p2の指すリストは何一つ変わらない。

それでは言語を変えて。

def func(array):
    array[0] = 10
    
def func2(array):
    array = [10, 2]
    
p1 = [1, 2]
p2 = [1, 2]

print( id(p1), id(p2), sep=', ')

func(p1)
func2(p2)

print( p1, p2, sep= ', ' )
print( id(p1), id(p2), sep=', ')

p2[1] = 20
print( id(p2), ',', sep= '', end='' )

p2 = [30, 40]
print( '', id(p2) )

# 出力結果
# 140422113705928, 140422113251528
# [10, 2], [1, 2]
# 140422113705928, 140422113251528
# 140422113251528, 140422113705160

p2に関してなんとも不思議な挙動をしている。
最後の行で示したように、p2[i] = n のようにリストの各要素の値を変更するだけでは、リストのidは変わらないが、
p2 = [n1, n2]のようにすると、リストのidは変わってしまう。
ということは、新しいリストを作成して、変数がその新しいリストを指すようになった、としか思えない。
だったら、func2でp2のidは変わらないとおかしくない?

PythonだけでなくRubyでも全く同じ結果で困惑している。

func2(p2)と書くところをfunc(p2)とタイプミスしてました。
正しく書くと完全に想定通りの結果でした。