不変型と可変型


186

不変型とは何なのか混乱しています。私のfloatオブジェクトが不変であると考えられていることを知っています。

class RoundFloat(float):
    def __new__(cls, val):
        return float.__new__(cls, round(val, 2))

これは、クラスの構造/階層のために不変であると見なされていますか?つまりfloat、クラスの最上位にあり、独自のメソッド呼び出しです。このタイプの例と似ています(たとえ私の本にdict変更可能とありますが):

class SortedKeyDict(dict):
    def __new__(cls, val):
        return dict.__new__(cls, val.clear())

これに対して、次のタイプの例では、ミュータブルにはクラス内にメソッドがあります。

class SortedKeyDict_a(dict):
    def example(self):
        return self.keys()

また、最後のについて、class(SortedKeyDict_a)このタイプのセットをそれに渡した場合:

d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))

exampleメソッドを呼び出さずに、辞書を返します。エラーとしてフラグを立てます。クラスに整数を渡してみましたが、エラーは報告されませんでした。SortedKeyDict__new__RoundFloat__new__


回答:


232

何?フロートは不変ですか?しかし、私はできません

x = 5.0
x += 7.0
print x # 12.0

その "mut" xではありませんか?

文字列は不変ですよね?しかし、あなたは同じことをすることができます。

s = 'foo'
s += 'bar'
print s # foobar

変数の値は変化しますが、変数が何を参照しているかを変更することで変化します。変更可能なタイプはそのように変更でき、「インプレース」でも変更できます。

ここに違いがあります。

x = something # immutable type
print x
func(x)
print x # prints the same thing

x = something # mutable type
print x
func(x)
print x # might print something different

x = something # immutable type
y = x
print x
# some statement that operates on y
print x # prints the same thing

x = something # mutable type
y = x
print x
# some statement that operates on y
print x # might print something different

具体例

x = 'foo'
y = x
print x # foo
y += 'bar'
print x # foo

x = [1, 2, 3]
y = x
print x # [1, 2, 3]
y += [3, 2, 1]
print x # [1, 2, 3, 3, 2, 1]

def func(val):
    val += 'bar'

x = 'foo'
print x # foo
func(x)
print x # foo

def func(val):
    val += [3, 2, 1]

x = [1, 2, 3]
print x # [1, 2, 3]
func(x)
print x # [1, 2, 3, 3, 2, 1]

5
あなたが説明することは私にとって意味します:可変変数は参照によって渡され、不変変数は値によって渡されます。これは正しいです ?
Lorenz Meyer

17
ほとんど、しかし正確ではありません。技術的には、すべての変数は、Pythonで参照渡しが、あなたのアナロジーにC. Aの反例の値によって、よりパスのような意味を持っているあなたが行う場合ですdef f(my_list): my_list = [1, 2, 3]。Cの参照渡しでは、引数の値はその関数を呼び出すことで変更できます。Pythonでは、その関数は何もしません。def f(my_list): my_list[:] = [1, 2, 3]何かします。
モーニング

6
ミュータブルな型はその場で変更できます。不変タイプはその場で変更できません。これがpythonが世界を見る方法です。変数が関数に渡される方法には関係ありません。
ychaouche 2014年

13
PythonのセマンティクスとC ++の参照渡しのセマンティクスの主な違いは、代入はPythonでは突然変異ではなく、C ++で行われることです。(しかし、もちろんのように、割り当てを増強しているという事実によって複雑だということa += b時々、突然変異。そして、実際には、より大きなオブジェクトの一部への割り当ては、時々その大きなオブジェクトの突然変異、パートなどのちょうど決して変異を意味することをa[0] = b変化させませんa[0]、しかしそれはおそらく変異しaます…C ++の観点から物事を入れようとせず、代わりにPythonが独自の用語で何をしているかを記述するほうがよいかもしれない理由です...)
abarnert

2
不変の意味を理解するために不可欠なid()を使用していないため、この回答は誤解を招くものでした。
pawel_winzig

185

Pythonはすべてのデータをオブジェクトとして表現することを理解する必要があります。リストや辞書などのこれらのオブジェクトの一部は変更可能です。つまり、IDを変更せずにコンテンツを変更できます。整数、浮動小数点数、文字列、タプルなどの他のオブジェクトは、変更できないオブジェクトです。これを理解する簡単な方法は、オブジェクトIDを確認することです。

以下に、不変の文字列が表示されます。その内容を変更することはできません。それは発生しますTypeError、あなたがそれを変更しようとした場合。また、新しいコンテンツを割り当てると、コンテンツが変更されるのではなく、新しいオブジェクトが作成されます。

>>> s = "abc"
>>>id(s)
4702124
>>> s[0] 
'a'
>>> s[0] = "o"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> s = "xyz"
>>>id(s)
4800100
>>> s += "uvw"
>>>id(s)
4800500

あなたはそれをリストで行うことができ、それはオブジェクトのアイデンティティを変更しません

>>> i = [1,2,3]
>>>id(i)
2146718700
>>> i[0] 
1
>>> i[0] = 7
>>> id(i)
2146718700

Pythonのデータモデルの詳細については、Python言語リファレンスをご覧ください。


4
+1 Pythonドキュメントへのリンク。しかし、今日はPython 2と3を区別する必要があることに気づくまで、しばらく時間がかかりました。それを強調するために回答を更新しました。
ベンジャミン

107

一般的な不変タイプ:

  1. 番号:int()float()complex()
  2. 不変のシーケンス:str()tuple()frozenset()bytes()

一般的な変更可能な型(ほとんどすべて):

  1. 可変シーケンス:list()bytearray()
  2. セットタイプ: set()
  3. マッピングタイプ: dict()
  4. クラス、クラスインスタンス

型が変更可能かどうかをすばやくテストする1つのトリックは、id()組み込み関数を使用することです。

例、整数での使用、

>>> i = 1
>>> id(i)
***704
>>> i += 1
>>> i
2
>>> id(i)
***736 (different from ***704)

リストで使用し、

>>> a = [1]
>>> id(a)
***416
>>> a.append(2)
>>> a
[1, 2]
>>> id(a)
***416 (same with the above id)

11
よく説明しました。によるチェックの概念が気に入りましたid()。+1。
Parag Tyagi 14

4
実際、id()ここでの使用は誤解を招くものです。指定されたオブジェクトは、存続期間中は常に同じIDを持ちますが、ガベージコレクションが原因で、異なる時間に存在する異なるオブジェクトが同じIDを持つ場合があります。
オーグラ2016

37

まず、クラスにメソッドがあるかどうか、またはクラスの構造が何であるかは、可変性とは関係ありません。

intsとfloatsは不変です。私が行った場合

a = 1
a += 5

それは最初の行のメモリのどこかに名前aを示し1ます。二行目では、それはそれを見上げ1、追加5取得、6その後、ポイントをaその時に6メモリに-それはなかった変更1への6任意の方法で。他の不変タイプを使用して、同じロジックが次の例に適用されます。

b = 'some string'
b += 'some other string'
c = ('some', 'tuple')
c += ('some', 'other', 'tuple')

以下のために変更可能なタイプ、私はactalllyこと行うことができ、それがメモリに保存されている値を変更します。と:

d = [1, 2, 3]

私はの場所のリスト作成した12と、3メモリ内に。私がそれなら

e = d

私はちょうどポイントe同じlist dでポイント。私はそれからできる:

e += [4, 5]

そして、両方のことをリストedの点でもの場所持っているように更新されます45、メモリ内に。

不変型に戻り、それを次のようにするとtuple

f = (1, 2, 3)
g = f
g += (4, 5)

その後 fまだオリジナルtupleのみを指します-あなたは完全に新しいものを指し示しgました。tuple

今、あなたの例で

class SortedKeyDict(dict):
    def __new__(cls, val):
        return dict.__new__(cls, val.clear())

あなたが通過する場所

d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))

(これtupletuplesような)valので、あなたがエラーを取得しているtupleのが持っていない.clear()方法を-あなたは合格する必要があるだろうdict(d)val仕事にそれのためにあなたが空に取得します。その場合には、SortedKeyDict結果としては。


2
これは非常に良い説明です。この質問と、それを説明するための多くの興味深い(新しい)視点が気に入りました。
失敗した科学者

25

他の言語(RubyのようにPythonによく似ている言語を除く)からPythonにアクセスする場合、その言語を他の言語の観点から理解するように強く要求する場合、通常、ここで混乱します。

>>> a = 1
>>> a = 2 # I thought int was immutable, but I just changed it?!

Pythonでは、割り当てはPythonの突然変異ではありません。

C ++では、を記述した場合a = 2、を呼び出します。a.operator=(2)これにより、に格納されているオブジェクトが変更されaます。(そして場合がありませんでしたに保存されているいかなるオブジェクトaエラーです。)

Pythonでは、a = 2に格納されたものには何もしませんa。代わりに2保存されていることを意味しaます。(そして、そこ場合ではなかったに保存されている何のオブジェクトは、a。)


最終的に、これはさらに深い違いの一部です。

C ++のような言語の変数は、メモリ内の型付きの場所です。場合aint、その意味では、コンパイラは次のように解釈されることになっていることを知っている4バイトのどこかですint。あなたが行うときに、a = 2それから、メモリのものを4バイトに格納されているものに変更0, 0, 0, 1します0, 0, 0, 2。別のint変数がどこかにある場合、それは独自の4バイトを持っています。

Pythonのような言語の変数は、独自の寿命を持つオブジェクトの名前です。数値1用のオブジェクトと、数値用の別のオブジェクトがあります2。また、aとして表される4バイトのメモリではintなく、単に1オブジェクトを指す名前です。a = 2数値1を数値2に変えることは意味がありません(これは、Pythonプログラマーに宇宙の基本的な仕組みを変更する力を与えすぎます)。代わりにa1オブジェクトを忘れて、2ます。


したがって、割り当てが変異でない場合、何変異は?

  • のように変更が記録されているメソッドを呼び出すa.append(b)。(これらのメソッドはほとんど常にを返すことに注意してくださいNone)。不変タイプにはそのようなメソッドはありませんが、通常、可変タイプにはあります。
  • a.spam = bまたはのように、オブジェクトの一部に割り当てるa[0] = b。不変タイプは属性または要素への割り当てを許可しません。可変タイプは通常どちらか一方を許可します。
  • のような拡張割り当てを使用するa += b場合とそうでない場合があります。変更可能な型は通常、値を変更します。不変タイプは決して実行せず、代わりにコピーを提供します(それらはを計算しa + b、結果をに割り当てaます)。

しかし、代入が変異ではない場合、オブジェクトの変異の一部にどのように代入するのでしょうか。それはそれがトリッキーになるところです。a[0] = bではない変異するa[0](C ++とは異なり、再び)が、それはないのmutateをa(C ++とは異なり、間接を除きます)。

これがすべて、Pythonのセマンティクスを慣れ親しんだ言語で表現しようとせ、代わりに独自の用語でPythonのセマンティクスを学ぶほうがよい理由です。


2
a = 'hi'と言います。a [0] = 'f'は 'print a' print out 'fi'(私は今のところ正しいですか?) ?a [n]にも独自の場所があり、その値を変更すると別の値を指すようになりますか?
Daniel Springer

19

オブジェクトが変更可能かどうかは、そのタイプによって異なります。これは、特定のメソッドがあるかどうかや、クラス階層の構造には依存しません。

ユーザー定義型(つまりクラス)は一般に変更可能です。不変タイプの単純なサブクラスなど、いくつかの例外があります。その他の不変のタイプには、いくつかの組み込み型のようなintfloattuplestr、だけでなく、いくつかのPythonのクラスはCで実装しました

「Python言語リファレンス」の「データモデル」の章の一般的な説明:

一部のオブジェクトの値は変化する可能性があります。値が変化する可能性のあるオブジェクトは、変更可能であると言われています。一度作成された値が変更できないオブジェクトは、不変と呼ばれます。

(変更可能なオブジェクトへの参照を含む不変のコンテナーオブジェクトの値は、後者の値が変更されると変更される可能性があります。ただし、コンテナーに含まれるオブジェクトのコレクションは変更できないため、コンテナーは不変と見なされます。したがって、不変性は厳密ではありません。変更不可能な値を持つのと同じで、より微妙です。)

オブジェクトの可変性は、そのタイプによって決まります。たとえば、数値、文字列、タプルは不変ですが、辞書やリストは変更可能です。


+1ただし、一部の拡張タイプ(その定義を確認する必要がある場合があります。Pythonのすべての組み込みタイプはCで実装されています)は不変です。その他(ほとんどの場合、あえて言っておきますが)は完全に変更可能です。

@delnan 「拡張機能タイプ」とは何ですか?
eyquem

@eyquem:私は「拡張タイプ」という用語を誤って使用しましたが、デルナンはそれを参照していました。彼のコメントの後、私は私の答えを修正し、この用語の使用を避けました。
taleinat

19

可変オブジェクトと不変オブジェクトの違い

定義

可変オブジェクト:作成後に変更できるオブジェクト。
不変オブジェクト:作成後に変更できないオブジェクト。

Pythonでは、不変オブジェクトの値を変更すると、新しいオブジェクトが作成されます。

可変オブジェクト

以下は、可変タイプのPythonのオブジェクトです。

  1. list
  2. Dictionary
  3. Set
  4. bytearray
  5. user defined classes

不変オブジェクト

次に、不変タイプのPythonのオブジェクトを示します。

  1. int
  2. float
  3. decimal
  4. complex
  5. bool
  6. string
  7. tuple
  8. range
  9. frozenset
  10. bytes

未回答の質問

質問文字列は不変の型ですか?
回答はい、そう ですが、これについて説明してください: 証明1

a = "Hello"
a +=" World"
print a

出力

"Hello World"

上記の例では、文字列は「Hello」として一度作成され、次に「Hello World」に変更されました。これは、文字列が可変タイプであることを意味します。しかし、それがアイデンティティをチェックして、それが変更可能な型であるかどうかを確認するときではありません。

a = "Hello"
identity_a = id(a)
a += " World"
new_identity_a = id(a)
if identity_a != new_identity_a:
    print "String is Immutable"

出力

String is Immutable

証明2

a = "Hello World"
a[0] = "M"

出力

TypeError 'str' object does not support item assignment

質問タプルは不変の型ですか?
回答はい、そうです。 証明1

tuple_a = (1,)
tuple_a[0] = (2,)
print a

出力

'tuple' object does not support item assignment

In [46]:a = "Hello" In [47]:id(a)Out [47]:140071263880128 In [48]:a = a.replace( "H"、 "g")In [49]:a Out [49]: 'gello' In [50]:id(a)Out [50]:140071263881040
Argus Malware

私の上記の例
Argusマルウェアの

アイテムの割り当ては、不変タイプでは問題になりません。あなたのケースでは、文字列aを変更していますが、メモリでは新しい変数に割り当てています。私の場合のアイテム割り当ては、リストや辞書の場合のように変数のメモリを変更しません。置換を行う場合は、既存の変数を変更せずに新しい変数を作成します
anand tripathi 2017年

@ArgusMalwareの場合、最初のIDはGCによってリサイクルされるため、2つのIDは等しいため、2番目のIDはメモリを再利用します。
コログラ

11

変更可能なオブジェクトには、少なくともオブジェクトを変更できるメソッドが必要です。たとえば、listオブジェクトにはappendメソッドがあり、実際にオブジェクトを変更します。

>>> a = [1,2,3]
>>> a.append('hello') # `a` has mutated but is still the same object
>>> a
[1, 2, 3, 'hello']

ただし、クラスにfloatは、floatオブジェクトを変更するメソッドはありません。できるよ:

>>> b = 5.0 
>>> b = b + 0.1
>>> b
5.1

しかし、=オペランドはメソッドではありません。変数とその右側にあるものをバインドするだけです。オブジェクトを変更または作成することはありません。これは、今後、変数が指すものの宣言です。

あなたが行う場合は、オペランドはのTE結果を使用して作成されたウィッヒ新しいfloat、に変数をバインドします 。b = b + 0.1=5 + 0.1

変数が既存のオブジェクト(変更可能かどうかに関係なく)に割り当てられると、=オペランドは変数をそのオブジェクトにバインドします。そして、これ以上何も起こりません

どちらの場合も、=バインドを作成するだけです。オブジェクトを変更または作成しません。

するとa = 1.0=オペランドはフロートを作成するのではなく1.0、ラインの一部になります。実際のところ、1.0これはfloat(1.0)floatオブジェクトを返すコンストラクター呼び出しの省略形です。(これが、タイプ1.0してEnterキーを押すと、「エコー」が1.0印刷される理由です。これが、呼び出したコンストラクター関数の戻り値です)

さて、あればbフロートであり、あなたが割り当てたa = bオブジェクトがinmutableあり、そしてあなたが行う場合ので、両方の変数が同じオブジェクトを指しているが、実際の変数は、自分自身comunicate betweemすることはできませんb += 1、今b新しいオブジェクトを指す、とaありますまだoldoneを指しており、何bを指しているのかわかりません。

しかし場合cである、のは、言わせてlist、あなたが割り当てたa = c今、aおよびcので、缶「comunicate」list変更可能である、とあなたがしなければc.append('msg')、その後、ちょうどチェックしa、あなたがメッセージを取得します。

(ちなみに、すべてのオブジェクトには一意のID番号が関連付けられているため、で取得できますid(x)。そのため、オブジェクトが同じかどうか、またはその一意のIDが変更されたかどうかを確認できます。)


6

クラスの各オブジェクトがインスタンス化時に固定値を持ち、その後変更できない場合、そのクラスは不変です

つまり、その変数の値全体を変更する(name)か、そのままにしておきます。

例:

my_string = "Hello world" 
my_string[0] = "h"
print my_string 

これは動作してhello worldを出力すると予想していましたが、次のエラーがスローされます。

Traceback (most recent call last):
File "test.py", line 4, in <module>
my_string[0] = "h"
TypeError: 'str' object does not support item assignment

通訳が言っています:この文字列の最初の文字は変更できません

stringそれを機能させるには、全体を変更する必要があります。

my_string = "Hello World" 
my_string = "hello world"
print my_string #hello world

この表を確認してください:

ここに画像の説明を入力してください

ソース


上に示したよりも簡潔な方法で、Python文字列のコンポーネントをどのように変更できますか?
ルークデイビス

@LukeDavisあなたができるmy_string = 'h' + my_string[1:]。これにより、my_stringという新しい文字列が生成され、元のmy_stringはなくなります(id(my_string)これを表示するには印刷してください)。より一般的な場合のために、非常に柔軟ではありませんもちろん、あなたはリストとバックに変換することができます:l = list(my_string) l[0] = 'h' my_string = ''.join(l)
ゼブラ

5

可変/不変が実際に何を意味するのかという問題に直面しているように思えます。だからここに簡単な説明があります:

まず、説明の基礎となる基盤が必要です。

そのため、仮想オブジェクトとしてプログラムするものは何でも考えてください。コンピューターのメモリに2進数のシーケンスとして保存されるものです。(ただし、これを想像しすぎないでください。^^)たいていのコンピューター言語では、これらの2進数を直接処理するのではなく、2進数の解釈を使用します。

たとえば、0x110、0xaf0278297319などの数値について考えるのではなく、6のような数値や「Hello、world」のような文字列について考えます。決してこれらの数または文字列は、コンピューターのメモリ内の2進数の解釈ではありません。変数のどの値にも同じことが言えます。

つまり実際の値ではなく、実際のバイナリ値の解釈を使用してプログラミングします。

これで、ロジックやその他の "きちんとしたもの"のために変更してはならない解釈がありますが、変更される可能性のある解釈もあります。たとえば、都市のシミュレーション、つまり多くの仮想オブジェクトがあり、それらのいくつかが家であるプログラムについて考えてみましょう。これらの仮想オブジェクト(家)を変更しても、同じ家と見なすことができますか?もちろん可能です。したがって、それらは変更可能です。「完全に」異なるオブジェクトになることなく変更できます。

整数について考えてみましょう。これらも仮想オブジェクト(コンピューターのメモリー内の2進数のシーケンス)です。では、そのうちの1つを変更した場合(値を6ずつ増やすなど)、それでも6ですか?もちろんそうではありません。したがって、どの整数も不変です。

したがって、仮想オブジェクトの変更が実際に別の仮想オブジェクトになることを意味する場合、それは不変と呼ばれます。

最後のコメント:

(1)変更可能および不変の実際の経験を特定の言語でのプログラミングと混同しないでください。

すべてのプログラミング言語には、ミュートされるオブジェクトとミュートされないオブジェクトの独自の定義があります。

そのため、意味の違いは理解できるかもしれませんが、各プログラミング言語の実際の実装を学ぶ必要があります。...確かに、6をミュートして7にする言語の目的があるかもしれません。そして、これもまた、パラレルユニバースのシミュレーションのような、かなりクレイジーで興味深いものです。^^

(2)この説明は確かに科学的ではなく、変更可能と不変の違いを理解するのに役立ちます。


5

この回答の目的は、単一の場所を作成して、変更/非変更(不変/変更可能)を処理しているかどうかを判断する方法に関するすべての優れたアイデアを見つけ、可能な場合、それに対して何をするかです。ミューテーションが望ましくなく、この点でのpythonの動作は、他の言語から入ってくるプログラマーに直観に反するように感じる場合があります。

@ mina-gabrielによる有用な投稿によると:

上記を分析し、@arrakëënによる投稿と組み合わせます:

予期せず変更できないものは何ですか?

  • スカラー(単一の値を格納する変数の型)が予期せず変更されない
    • 数値の例:int()、float()、complex()
  • 「可変シーケンス」がいくつかあります。
    • str()、tuple()、frozenset()、bytes()

なにができる?

  • オブジェクトのようなリスト(リスト、辞書、セット、bytearray())
  • ここの投稿には、クラスとクラスインスタンスも記載されていますが、これは、クラスの継承元や構築方法に依存する場合があります。

「予期せず」とは、他の言語のプログラマーがこの動作を期待しない可能性があることを意味します(例外またはRuby、およびおそらく他のいくつかの「Pythonのような」言語)。

このディスカッションに追加:

この動作は、メモリを食う大きなデータ構造の複数のコピーが誤ってコードに入力されるのを防ぐときに有利です。しかし、これが望ましくない場合、どうすればそれを回避できますか?

リストを使用する場合、簡単な解決策は次のように新しいリストを作成することです。

list2 = list(list1)

他の構造では...ソリューションはよりトリッキーになる可能性があります。1つの方法は、要素をループしてそれらを(同じ型の)新しい空のデータ構造に追加することです。

可変構造を渡すと、関数はオリジナルを変更できます。見分け方は?

  • このスレッドの他のコメントにいくつかのテストが与えられていますが、これらのテストが完全な証明ではないことを示すコメントがあります
  • object.function()は元のオブジェクトのメソッドですが、これらの一部のみが変化します。何も返さない場合は、おそらく返します。.append()は、名前を指定してテストせずに変異することを期待します。.union()はset1.union(set2)の和集合を返し、変化しません。疑わしい場合は、関数で戻り値を確認できます。return = Noneの場合、変化しません。
  • 場合によっては、sorted()が回避策になることがあります。オリジナルのソートされたバージョンを返すため、他の方法でオリジナルの作業を開始する前に、変更されていないコピーを保存できます。ただし、このオプションは、元の要素の順序を気にしないことを前提としています(行う場合は、別の方法を見つける必要があります)。対照的に、.sort()は(予想されるように)オリジナルを変更します。

非標準的なアプローチ(役立つ場合):MITライセンスで公開されているgithubでこれを見つけました:

  • githubリポジトリー:tobgu名前:pyrsistent
  • 内容:ミューテーションが望ましくない場合にコアデータ構造の代わりに使用するように記述されたPython永続データ構造コード

カスタムクラスの場合、@ semicolonは__hash__関数が存在するかどうかを確認することを提案します。これは、可変オブジェクトには通常__hash__()関数が含まれていないためです。

これが、今のところこのトピックについて学んだすべてです。他のアイデア、修正などは大歓迎です。ありがとう。


3

違いを考える1つの方法:

Pythonの不変オブジェクトへの割り当ては深いコピーと考えることができますが、可変オブジェクトへの割り当ては浅いです


1
これは誤りです。Pythonでの割り当てはすべて参照によるものです。コピーは含まれません。
オーギュラー16

3

最も簡単な答え:

可変変数とは、値が適切に変化する可能性がある変数ですが、不変変数では、値が変化しません。不変変数を変更すると、同じ変数が再構築されます。

例:

>>>x = 5

xによって参照される値5を作成します

x-> 5

>>>y = x

このステートメントは、yにxの5を参照させます。

x -------------> 5 <----------- y

>>>x = x + y

xが整数(不変タイプ)であるため、再構築されました。

ステートメントでは、RHSの式は値10になり、これがLHS(x)に割り当てられると、xは10に再構築されます。

x ---------> 10

y ---------> 5


-1

すべての回答を読んだわけではありませんが、選択した回答は正しくありません。作成者は、変数を再割り当てできるということは、どのデータ型も変更可能であることを意味すると考えています。そうではありません。可変性は、値で渡すのではなく、参照で渡すことに関係しています。

リストを作成したとしましょう

a = [1,2]

あなたが言うなら:

b = a
b[1] = 3

Bの値を再割り当てした場合でも、aの値を再割り当てします。その理由は、「b = a」を割り当てた場合です。値のコピーではなく、オブジェクトに「参照」を渡しています。これは、文字列、浮動小数点数などの場合には当てはまりません。これにより、リスト、辞書などが変更可能になりますが、ブール値、浮動小数点数などは不変になります。


-1

不変オブジェクトの場合、割り当てにより、たとえば値の新しいコピーが作成されます。

x=7
y=x
print(x,y)
x=10 # so for immutable objects this creates a new copy so that it doesnot 
#effect the value of y
print(x,y)

変更可能なオブジェクトの場合、割り当てによって値の別のコピーが作成されることはありません。例えば、

x=[1,2,3,4]
print(x)
y=x #for immutable objects assignment doesn't create new copy 
x[2]=5
print(x,y) # both x&y holds the same list

1
間違いです。割り当てによってコピーが作成されることはありませんnedbatchelder.com/text/names.htmlをお読みください。 最初のケースでx=10は、ミューテーターメソッドを呼び出しながら、単に別の割り当てx[2] = 5です。intオブジェクトには単にミューテーターメソッドがありませんが
juanpa.arrivillaga

-2

Pythonでは、簡単に知る方法があります。

不変:

    >>> s='asd'
    >>> s is 'asd'
    True
    >>> s=None
    >>> s is None
    True
    >>> s=123
    >>> s is 123
    True

可変:

>>> s={}
>>> s is {}
False
>>> {} is {}
Flase
>>> s=[1,2]
>>> s is [1,2]
False
>>> s=(1,2)
>>> s is (1,2)
False

そして:

>>> s=abs
>>> s is abs
True

だから組み込み関数もPythonでは不変だと思います。

しかし、フロートがどのように機能するかは本当にわかりません:

>>> s=12.3
>>> s is 12.3
False
>>> 12.3 is 12.3
True
>>> s == 12.3
True
>>> id(12.3)
140241478380112
>>> id(s)
140241478380256
>>> s=12.3
>>> id(s)
140241478380112
>>> id(12.3)
140241478380256
>>> id(12.3)
140241478380256

変だ。


しかし、それは明らかに有効ではありません。タプルは不変だからです。入力してx = (1, 2)から、変更してみてくださいx。不可能です。可変性を確認するために私が見つけた1つの方法はhash、少なくとも組み込みオブジェクトに対して機能することです。hash(1) hash('a') hash((1, 2)) hash(True)すべてが機能し、hash([]) hash({}) hash({1, 2})すべてが機能しません。
セミコロン

@semicolonユーザー定義のクラスのhash()場合、__hash__()ユーザー定義のクラスは一般的に変更可能ですが、オブジェクトがメソッドを定義している場合は機能します。
オーグラ2016

1
@augurarはい、という意味ですが、Pythonでは実際の静的型付けや正式な保証がないため、Pythonでは何も保証されません。ただし、hash可変オブジェクトには一般に__hash__()メソッドが含まれていないはずです。ディクショナリでキーを作成することは危険なので、このメソッドは非常に優れています。
セミコロン

1
@augurarとセミコロン(または、知っている場合は他の人):__hash __()ソリューション...カスタムクラスの作成者は、カスタムクラスを作成するためにそれを追加する必要がありますか?その場合、ルールは存在する場合、オブジェクトは不変である必要があります。存在しない場合は、作成者がオフになっているだけで終了した可能性があるため、わかりません。
TMWP 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.