私がこのコードを書くとき:
polly = "alive"
palin = ["parrot", polly]
print(palin)
polly = "dead"
print(palin)
私はそれがこれを出力すると思った:
"['parrot', 'alive']"
"['parrot', 'dead']"
ただし、そうではありません。それを出力するにはどうすればよいですか?
Python変数は値への参照を保持します。したがって、palin
リストを定義するときpolly
は、変数自体ではなく、によって参照される値を渡します。
値をバルーンとして想像する必要があります。変数はそれらのバルーンに関連付けられたスレッドです。"alive"
はバルーンでpolly
あり、そのバルーンへの単なるスレッドであり、palin
リストには同じバルーンに関連付けられた別のスレッドがあります。Pythonでは、リストは単純に一連のスレッドであり、すべて0から始まる番号が付けられています。
次に行うことは、polly
文字列を新しいバルーン"dead"
に結び付けることですが、リストはバルーンに結び付けられた古いスレッドを保持しています"alive"
。
"alive"
各スレッドを参照するようにリストをインデックスで再割り当てすることにより、そのスレッドをリストによって保持されているスレッドに置き換えることができます。あなたの例では、それはスレッド1
です:
>>> palin[1] = polly
>>> palin
['parrot', 'dead']
ここでは、palin[1]
スレッドを同じものに結び付けただけpolly
です。
、、、などdict
のPythonのコレクションも、単なるスレッドのコレクションであることに注意してください。これらのいくつかは、リストやdictなど、スレッドを別のスレッドに交換することができます。これにより、Pythonの何かが「可変」になります。set
tuple
一方、文字列は変更できません。"dead"
またはのような文字列を定義すると"alive"
、それは1つのバルーンになります。スレッド(変数、リストなど)で結び付けることはできますが、その中の文字を置き換えることはできません。そのスレッドを完全に新しい文字列に結び付けることしかできません。
Pythonのほとんどのものは、風船のように機能します。整数、文字列、リスト、関数、インスタンス、クラス、すべてを変数に関連付けることも、コンテナーに関連付けることもできます。
Python名に関するNedBatchelderの論文も読むことをお勧めします。
2番目のprintステートメントの前に、新しい値を次の場所に保存しますpalin
。
palin = ["parrot", polly]
文字列をリストに入れると、リストには文字列のコピーが保持されます。文字列が元々変数であったか、リテラル値であったか、関数呼び出しの結果であったか、または他の何かであったかは関係ありません。リストに表示されるまでには、それは単なる文字列値です。後で文字列を生成したものを変更しても、リストに影響はありません。
値が変更されたときに通知される値への参照を保存する場合、通常のメカニズムは、「参照された」値を含むリストを使用することです。これを例に適用すると、ネストされたリストになります。例:
polly = ["alive"]
palin = ["parrot", polly]
print(palin)
polly[0] = "dead"
print(palin)
リストには値のみが含まれ、必要に応じて変数への参照は含まれません。ただし、ラムダをリストに格納し、ラムダに変数の値を検索させることはできます。
>>> a = 'a'
>>> list = ['a',lambda: a]
>>> list[1]
<function <lambda> at 0x7feff71dc500>
>>> list[1]()
'a'
>>> a = 'b'
>>> list[1]()
'b'
できません。ベアネームへの割り当てはPythonであり、常に名前を再バインドするだけであり、この操作をカスタマイズまたは監視することはできません。
できることはpolly
、文字列の代わりに可変オブジェクトを作成し、名前を再バインドする代わりにその値を変更することです。簡単な例:
>>> polly = ['alive']
>>> items = ['parrot', polly]
>>> items
['parrot', ['alive']]
>>> polly[0] = 'dead'
>>> items
['parrot', ['dead']]
他の回答は、何がうまくいっているのかを説明しています。
これは、オブジェクトの使用を動機付ける(いくつかの)問題の1つです。たとえば、次のようにします。
class Animal:
def __init__(self, aniType, name):
self.aniType = aniType
self.name = name
self.isAlive = True
def kill(self):
self.isAlive = False
def getName(self):
return self.name
def getType(self):
return self.aniType
def isLiving(self):
return self.isAlive
polly = Animal("parrot", "polly")
print(polly.getName()+' the '+polly.getType()+' is alive?')
print(polly.isLiving())
polly.kill()
print(polly.getName()+' the '+polly.getType()+' is alive?')
print(polly.isLiving())
単純なタスクの場合、最初は多くのコードのように見えるかもしれませんが、オブジェクトはすべてを整理するのに役立つため、このようなことを行うための方法であることがよくあります。
そのプログラムの出力は次のとおりです。
polly the parrot is alive?
True
polly the parrot is alive?
False