web-dev-qa-db-ja.com

Pythonで値を渡す

リストのようなコレクション、Pythonの別の関数に配列を渡すとき、それはコピーを作成しますか、それとも単なるポインタですか?

57
Joan Venge

Python 値への参照をオブジェクトに渡します

Pythonはオブジェクトへの参照を値(Javaなど)で渡し、Pythonのすべてがオブジェクトです。これは単純に聞こえますが、一部のデータ型はパスバイを示すように見えることに気付くでしょう-値の特性、他の人は参照渡しのように動作するように見えますが...取引は何ですか?

可変および不変オブジェクトを理解することが重要です。文字列、タプル、数値などの一部のオブジェクトは不変です。関数/メソッド内で変更すると、新しいインスタンスが作成され、関数/メソッド外の元のインスタンスは変更されません。リストや辞書などの他のオブジェクトは可変です。つまり、オブジェクトをその場で変更できます。したがって、関数/メソッド内のオブジェクトを変更すると、元のオブジェクトも外部に変更されます。

80
Stephen

つまり、参照/値の概念全体がpythonに適合しません。 Pythonには変数の「値」がありません。Pythonにはオブジェクトとオブジェクトを参照する名前のみがあります。

したがって、関数を呼び出して、次のように括弧内に「名前」を入れると:

def func(x): # defines a function that takes an argument
    ... # do something here

func(myname) # calling the function

namemynameitselfではなく、mynameが指している実際のオブジェクトが渡されます。関数内では別の名前x)が渡され、同じオブジェクトを参照します。

関数内のオブジェクトは変更可能であれば変更できますが、外部名が指しているものは変更できませんです。あなたがするときに起こることと同じ

anothername = myname

したがって、私はあなたの質問に答えることができます:

「値渡し」ですが、すべての値はオブジェクトへの単なる参照です。

69
nosklo

ここでの回答は役に立ちましたが、これまで見たことのないこのすばらしい区別を示す必要性があります。これについては、後続のCL実験で証明しました。

  1. 不変オブジェクトは、関数呼び出し内で変更することはできません。(これまでのところ、答えは多くを述べています...)
  2. ただし、可変オブジェクト内に含まれる不変オブジェクトは、メソッド呼び出し内で再割り当てできます。

「num」は不変のNumberオブジェクトであるため、ここでは変更されません[私のポイント1をサポートします]:

def incr_num(num):
    num += 1

num = 0

num
0

incr_num(num)

num
0

ここでの 'list [0]'は不変のNumberオブジェクトでもあります。

def incr_list(list):
    list[0] += 1

list = [0]

list[0]
0

incr_list(list)

list[0]
1

では、不変のNumberオブジェクトである「list [0]」はどのように変更されましたか(私のポイント2をサポート)、上記の例のNumberオブジェクト「num」は変更されませんでしたか?不変のNumberオブジェクト'list [0]'は可変リストオブジェクト 'list'に含まれますが、最初の例の 'num'は単なる非連結のNumberオブジェクトです。

よく意図されていますが、私は @ Stephen Pape 最高評価の回答(以下に引用)、および他のいくつかの同様の回答が完全に正しくなかったと感じています(そして、それがこの回答を書く動機になりました):

文字列、タプル、数値などの一部のオブジェクトは不変です。関数/メソッド内で変更すると、新しいインスタンスが作成され、関数/メソッド外の元のインスタンスは変更されません。

上記の2回目のコード実験では、Numberオブジェクト( 'list [0]')がメソッド内で変更され、その後関数外の元のインスタンスが変更されたことが示されています。

23
cellepo

参照は渡されますが、パラメーターが不変オブジェクトである場合、メソッド内でパラメーターを変更すると新しいインスタンスが作成されます。

6
anthony

オブジェクトが渡されます。コピーではなく、基礎となるオブジェクトへの参照。

4
S.Lott

copyモジュールを見ることもお勧めします。

コピーのPythonドキュメント

根本的な問題と、それを使用して独自のディープコピーを実行する方法を理解するのに役立ちます。

3
Matt

参照により:

>>> x = [0,1,2,3]
>>> def foo(x_list):
    x_list[0] = 1


>>> foo(x)
>>> x
[1, 1, 2, 3]
2
Harper Shelby

謙虚な例を挙げてください

def swap(a, b):
    x = a
    print id(x)
    print id(a)
    print id(b)
    a = b

    print id(a)
    b = x
    print id(b)
    a[0]= '20'




var1 = ['1','2','3','4']
var2 = ['5','6','7','8','9']
print id(var1)
print id(var2)

swap(var1, var2)

print id(var1)
print id(var2)
print var1
print var2

次の結果が生成されます

28329344 var1 28331264 var2 28329344 x 28329344 a 28331264 b a = bの後28331264 a b = x 28329344 bの後復帰後28329344 var1 28331264 var2 ['1'、 '2'、 '3'、 '4'] ['20'、 「6」、「7」、「8」、「9」]

メモリアドレスへのマッピング28329344 28331264 var1 var2 abx a = baの後b = xbの後a [0] = '20' [0] = '20'戻り後['1'、 '2'、 '3'、 ' 4 '] [' 20 '、' 6 '、' 7 '、' 8 '、' 9 ']

0
Antonio Leite