目次
Pythonの可変オブジェクトと不変オブジェクト
可変/不変オブジェクトとは
不可变对象的例子
可变对象的例子
作为函数参数
有趣的例子
ホームページ バックエンド開発 Python チュートリアル Pythonの可変オブジェクトと不変オブジェクトについて詳しく解説

Pythonの可変オブジェクトと不変オブジェクトについて詳しく解説

Jun 30, 2017 pm 02:30 PM
python 不変 物体

Pythonの可変オブジェクトと不変オブジェクト

可変/不変オブジェクトとは

  • 不変オブジェクト、オブジェクトが指すメモリ内の値は変更できません。 変数を変更する場合、参照する値は変更できないため、元の値をコピーして変更することと同じになり、新しいアドレスが開かれ、変数はこの新しいアドレスを指します。

  • Mutable オブジェクト。オブジェクトが指すメモリ内の値は変更できます。 変数 (正確には参照) が変更された後、それが参照する値は実際には直接変更され、コピーは行われず、新しい送信アドレスは開かれません。平たく言えば、その場で変更されるということです。

Python では、

数値型 (intfloat)、文字列 str、タプル tuple はすべて不変型です。リスト、ディクショナリ、セットは変数タイプです。 intfloat)、字符串str、元组tuple都是不可变类型。而列表list、字典dict、集合set是可变类型。

还是看代码比较直观。先看不可变对象

不可变对象的例子

先说明一点is 就是判断两个对象的id是否相同, 而 == 判断的则是内容是否相同。

a = 2b = 2c = a + 0 c += 0print(id(a), id(b), id(2))  # id都相同print(c is b) #True
ログイン後にコピー

再来看字符串

astr = 'good'bstr = 'good'cstr = astr + ''print(cstr is bstr) # Trueprint(id(astr), id(bstr), id('good'))  # 三个id相同
ログイン後にコピー

和数值类型的结果一样。如果是下面这种情况,变量修改后不在是good

astr = 'good'print(id(astr))
astr += 'aa'print(id(astr)) # id和上面的不一样
ログイン後にコピー

由于是不可变对象,变量对应内存的值不允许被改变。当变量要改变时,实际上是把原来的值复制一份后再改变,开辟一个新的地址,astr再指向这个新的地址(所以前后astr的id不一样),原来astr对应的值因为不再有对象指向它,就会被垃圾回收。这对于int和float类型也是一样的。

再看tuple

add = (1, 2, 3)
aee = (1, 2, 3)print(id(add), id(aee), id((1, 2, 3)))  # id各不相同aee = (1, 2, 3)print(id(aee))
aee += () # 加空元组print(id(aee))  # id变了!print(aee)  #(1 ,2,3)
ログイン後にコピー

虽然看上去都是(1 ,2, 3)按理说应该和上面一致才对。难道这是可变对象?再看

add = (1, 2, 3)
aee = add 
print(id(aee), id(add)) # 这两个id一样aee += (4, 5, 6)print(id(aee)) # aee的id变了!print(add) # add还是(1, 2, 3)没有变
ログイン後にコピー

又和数值类型于str类型一致了。如果是可变对象add = aee,它们指向同一地址(id相同)是肯定的。但不是同一对象的不同引用,因为如果是的话,aee的改变会引起add的改变,再tuple中并不是这样。所以tuple是不可变对象,但又和str和数值类型稍微有点区别。平常说的tuple不可变更多时候是指里面存放的值不能被改变(有些特殊情况,如tuple里面存放了list,可改变list里的元素。但实际上这个tuple并没有被改变)。

对于str、int、float只要在它们再类型相同的情况下,值也相同,那么它们的id相同。(为什么要说类型相同?)

a = 2.0b = 2print(a is b)  # False, 一个int一个float,类型都不同
ログイン後にコピー

2和2.0就不在一个地址上。

可变对象的例子

lis = [1, 2, 3]
lis2 = [1, 2, 3]# 虽然它们的内容一样,但是它们指向的是不同的内存地址print(lis is lis2)print(id(lis), id(lis2), id([1, 2, 3]))  # 三个id都不同
ログイン後にコピー

再看赋值的情况下

alist = [1, 2, 3]# alist实际上是对对象的引用,blist = alist即引用的传递,现在两个引用都指向了同一个对象(地址)blist = alistprint(id(alist), id(blist))  # id一样# 所以其中一个变化,会影响到另外一个blist.append(4)print(alist)  # 改变blist, alist也变成了[1 ,2 ,3 4]print(id(alist), id(blist))  # id一样,和上面值没有改变时候的id也一样
ログイン後にコピー

blist = alist这一句。alist实际上是对对象的引用,blist = alist即引用的传递,现在两个引用都指向了同一个对象(地址)。所以其中一个变化,会影响到另外一个。

再看看set

abb = {1, 2, 3}
acc = abbprint(id(abb), id(acc))
acc.add(4)print(abb)  # {1, 2, 3, 4} print(id(abb), id(acc)) # 相等
ログイン後にコピー

和上面list的例子一致。

可变对象由于所指对象可以被修改,所以无需复制一份之后再改变,直接原地改变,所以不会开辟新的内存,改变前后id不变。

当然不可变对象就不是这样了, 可以和这个对比一下

abc = 3dd = abc
dd = 43print(abc)  # 3,并不随dd的改变而改变
ログイン後にコピー

但是如果是拷贝,就仅仅是将内容拷贝过去,传递的并是不引用。这在想使用列表的值又不想修改原列表的时候特别有用。

blist = alist[:]  # or alist.copy()print(alist is blist)  # Falseblist.append(4)print(alist)  # 还是[1,2 ,3]没有变化
ログイン後にコピー

作为函数参数

作为函数参数,也是一样的,可变类型传递的是引用,不可变类型传递的是内容。

test_list = [1, 2, 3, 4]
test_str = 'HAHA'def change(alist):
    alist.append(5)def not_change(astr):
    astr.lower()


change(test_list)
not_change(test_str)print(test_list)  # 改变了原来的值print(test_str)  # 没有变
ログイン後にコピー

当然了,如果不想改变原来列表的值,参数可以传入列变的拷贝。alsit[:]

有趣的例子

再看一个有趣的例子,我们知道list是可以使用+添加一个列表的。

a1 = [1, 2, 3]
a2 = a1print(id(a1), id(a2))# 实际上是a2指向了新的对象,id已经改变。# 所以现在a2、a1并不是同一对象的两个引用了,a2变化a1不会改变a2 = a2 + [4] # 这个等式中,右边的a2还是和a1的id一样的,一旦赋值成功,a2就指向新的对象print(id(1), id(a2))  # 不等,a2的id变化了print(a1) # [1, 2, 3]没有变
ログイン後にコピー

如果是这样写

a1 = [1, 2, 3]
a2 = a1print(id(a1), id(a2))
a2 += [4]  # 相当于调用了a2.extend([4]),原地改变并没有新的对象产生print(id(1), id(a2))  # 相等,a2的id没有变化print(a1)
ログイン後にコピー

不同的地方在于a2 += [4],这句相当于调用了a2.extend([4])

コードを見るとより直感的です。まず不変オブジェクトの例を見てみましょう🎜🎜不変オブジェクト🎜🎜🎜 まず最初に、== の間、<code>is は 2 つのオブジェクトの ID が同じかどうかを判断することであることを説明しましょう。 は内容が同じかどうかを判断します。 🎜🎜
rrreee
🎜文字列 🎜
rrreee
を見てください。結果は数値型と同じです。次の状況が発生した場合、変数はもはや good ではありません🎜
rrreee
🎜🎜 不変オブジェクトであるため、変数に対応するメモリの値は変数を変更することはできません。変数を変更する場合、実際には元の値がコピーされてから変更され、新しいアドレスが開かれ、astr はこの新しいアドレスを指します(したがって、前と前の astr の ID は異なります)。元の astr は異なります。別のオブジェクトがそれを指している場合、それはガベージ コレクションされるからです。 🎜これはint型とfloat型の場合も同様です。 🎜🎜タプルをもう一度見てください🎜
rrreee
🎜それらはすべて (1,2, 3) であるように見えますが、その上。これは可変オブジェクトですか?もう一度見てください 🎜
rrreee
🎜 は、数値型と str 型と一致しています。それが可変オブジェクト add = aee である場合、それらが同じアドレス (同じ ID) を指していることは確実です。ただし、これは同じオブジェクトへの異なる参照ではありません。そうである場合、aee の変更により add の変更が発生しますが、タプルの場合はそうではありません。したがって、タプルは不変オブジェクトですが、str 型や数値型とは少し異なります。タプルの不変性は、通常、そこに格納されている値が変更できないことを意味します (🎜タプルに格納されたリストなど、一部の特殊なケースでは、リスト内の要素は変更できます。しかし実際には、タプルは変更されていません)変わりました🎜)。 🎜🎜 str、int、float の場合、同じ型と同じ値を持つ限り、それらの ID は同じになります。 (なぜ同じ型だと言えるのでしょうか?) 🎜
rrreee
🎜2 と 2.0 は同じアドレスにありません。 🎜🎜変数オブジェクトの例🎜
rrreee
🎜代入の場合を見てみましょう🎜
rrreee
🎜blist = alistこの文。 🎜<code>alist は実際にはオブジェクトへの参照であり、blist = alist は参照の転送であり、両方の参照が同じオブジェクト (アドレス) を指すようになりました。したがって、一方の変更は他方にも影響します。 🎜🎜🎜set を見てください🎜
rrreee
🎜上記のリストの例と一致しています。 🎜🎜 指定されたオブジェクトは変更できるため、コピーを作成して変更する必要はなく、その場で直接変更できるため、新しいメモリが開かれることはなく、変更の前後で ID は変わりません。 🎜🎜 もちろん、これは不変オブジェクトの場合には当てはまりません。🎜
rrreee
🎜 ただし、コピーの場合は、コンテンツをコピーして渡すだけです。参照なしで。 🎜これは、元のリストを変更せずにリストの値を使用したい場合に特に便利です。 🎜🎜
rrreee
🎜関数のパラメータとして🎜🎜 関数のパラメータとして、変数型は参照を渡し、不変型はコンテンツを渡します。 🎜
rrreee
🎜 もちろん、元のリストの値を変更したくない場合は、パラメータを列変数のコピーで渡すことができます。 alsit[:]🎜🎜興味深い例🎜🎜別の興味深い例を見ると、+ を使用してリストをリストに追加できることがわかります。 🎜
rrreee
🎜このように書くと 🎜
rrreee
🎜違いは a2 += [4] の場合、この文は <code>a2.extend([4]) を呼び出すことと同等であり、その場で変更することと同等であり、新しいオブジェクトは生成されません。 🎜

以上がPythonの可変オブジェクトと不変オブジェクトについて詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

携帯電話でXMLをPDFに変換するとき、変換速度は高速ですか? 携帯電話でXMLをPDFに変換するとき、変換速度は高速ですか? Apr 02, 2025 pm 10:09 PM

Mobile XMLからPDFへの速度は、次の要因に依存します。XML構造の複雑さです。モバイルハードウェア構成変換方法(ライブラリ、アルゴリズム)コードの品質最適化方法(効率的なライブラリ、アルゴリズムの最適化、キャッシュデータ、およびマルチスレッドの利用)。全体として、絶対的な答えはなく、特定の状況に従って最適化する必要があります。

携帯電話のXMLファイルをPDFに変換する方法は? 携帯電話のXMLファイルをPDFに変換する方法は? Apr 02, 2025 pm 10:12 PM

単一のアプリケーションで携帯電話でXMLからPDF変換を直接完了することは不可能です。クラウドサービスを使用する必要があります。クラウドサービスは、2つのステップで達成できます。1。XMLをクラウド内のPDFに変換し、2。携帯電話の変換されたPDFファイルにアクセスまたはダウンロードします。

C言語合計の機能は何ですか? C言語合計の機能は何ですか? Apr 03, 2025 pm 02:21 PM

C言語に組み込みの合計機能はないため、自分で書く必要があります。合計は、配列を通過して要素を蓄積することで達成できます。ループバージョン:合計は、ループとアレイの長さを使用して計算されます。ポインターバージョン:ポインターを使用してアレイ要素を指し示し、効率的な合計が自己概要ポインターを通じて達成されます。アレイバージョンを動的に割り当てます:[アレイ]を動的に割り当ててメモリを自分で管理し、メモリの漏れを防ぐために割り当てられたメモリが解放されます。

XMLをPDFに変換できるモバイルアプリはありますか? XMLをPDFに変換できるモバイルアプリはありますか? Apr 02, 2025 pm 09:45 PM

XML構造が柔軟で多様であるため、すべてのXMLファイルをPDFSに変換できるアプリはありません。 XMLのPDFへのコアは、データ構造をページレイアウトに変換することです。これには、XMLの解析とPDFの生成が必要です。一般的な方法には、ElementTreeなどのPythonライブラリを使用してXMLを解析し、ReportLabライブラリを使用してPDFを生成することが含まれます。複雑なXMLの場合、XSLT変換構造を使用する必要がある場合があります。パフォーマンスを最適化するときは、マルチスレッドまたはマルチプロセスの使用を検討し、適切なライブラリを選択します。

推奨されるXMLフォーマットツール 推奨されるXMLフォーマットツール Apr 02, 2025 pm 09:03 PM

XMLフォーマットツールは、読みやすさと理解を向上させるために、ルールに従ってコードを入力できます。ツールを選択するときは、カスタマイズ機能、特別な状況の処理、パフォーマンス、使いやすさに注意してください。一般的に使用されるツールタイプには、オンラインツール、IDEプラグイン、コマンドラインツールが含まれます。

携帯電話でXMLをPDFに変換する方法は? 携帯電話でXMLをPDFに変換する方法は? Apr 02, 2025 pm 10:18 PM

携帯電話でXMLをPDFに直接変換するのは簡単ではありませんが、クラウドサービスの助けを借りて実現できます。軽量モバイルアプリを使用してXMLファイルをアップロードし、生成されたPDFを受信し、クラウドAPIで変換することをお勧めします。クラウドAPIはサーバーレスコンピューティングサービスを使用し、適切なプラットフォームを選択することが重要です。 XMLの解析とPDF生成を処理する際には、複雑さ、エラー処理、セキュリティ、および最適化戦略を考慮する必要があります。プロセス全体では、フロントエンドアプリとバックエンドAPIが連携する必要があり、さまざまなテクノロジーをある程度理解する必要があります。

XMLを写真に変換する方法 XMLを写真に変換する方法 Apr 03, 2025 am 07:39 AM

XMLは、XSLTコンバーターまたは画像ライブラリを使用して画像に変換できます。 XSLTコンバーター:XSLTプロセッサとスタイルシートを使用して、XMLを画像に変換します。画像ライブラリ:PILやImageMagickなどのライブラリを使用して、形状やテキストの描画などのXMLデータから画像を作成します。

XML形式を開く方法 XML形式を開く方法 Apr 02, 2025 pm 09:00 PM

ほとんどのテキストエディターを使用して、XMLファイルを開きます。より直感的なツリーディスプレイが必要な場合は、酸素XMLエディターやXMLSPYなどのXMLエディターを使用できます。プログラムでXMLデータを処理する場合、プログラミング言語(Pythonなど)やXMLライブラリ(XML.ETREE.ELEMENTTREEなど)を使用して解析する必要があります。

See all articles