28

CPython(他のPython実装についての手がかりがない)が次のように動作するのはなぜですか?

tuple1 = ()
tuple2 = ()                                                                                                   
dict1 = {}
dict2 = {}
list1 = []
list2 = []
# makes sense, tuples are immutable
assert(id(tuple1) == id(tuple2))
# also makes sense dicts are mutable
assert(id(dict1) != id(dict2))
# lists are mutable too
assert(id(list1) != id(list2))
assert(id(()) == id(()))
# why no assertion error on this?
assert(id({}) == id({}))
# or this?
assert(id([]) == id([]))

理由はいくつかありますが、具体的な理由がわかりません

編集

グレンとトーマスの主張をさらに証明するには:

[1] id([])
4330909912
[2] x = []
[3] id(x)
4330909912
[4] id([])
4334243440
4

3 に答える 3

45

を呼び出すとid({})、Pythonはdictを作成し、それをid関数に渡します。関数はそのidID(そのメモリ位置)を取得し、dictを破棄します。口述は破棄されます。(その間に他のdictが作成されることなく)2回続けて実行すると、Pythonが2回目に作成するdictは、1回目と同じメモリブロックを使用します。(CPythonのメモリアロケータは、思ったよりもはるかに可能性が高くなります。)(CPythonでは)idメモリの場所をオブジェクトIDとして使用するため、2つのオブジェクトのIDは同じです。dictを変数に割り当ててから、そのdictを取得した場合、これは明らかに発生しません。これは、dictが同時に有効id()あるため、異なる必要があるためです。id

可変性は直接関係しませんが、タプルと文字列をキャッシュするコードオブジェクトは関係します。同じコードオブジェクト(関数またはクラス本体またはモジュール本体)で、同じリテラル(整数、文字列、および特定のタプル)が再利用されます。可変オブジェクトは再利用できません。常に実行時に作成されます。

つまり、オブジェクトのIDは、オブジェクトの存続期間中のみ一意です。オブジェクトが破棄された後、または作成される前に、他の何かが同じIDを持つことができます。

于 2010-10-06T22:08:56.623 に答える
42

CPythonは、オブジェクトがスコープ外になるとすぐにガベージコレクションを行うため[]、最初のオブジェクトが収集された後に2番目のオブジェクトが作成さ[]れます。したがって、ほとんどの場合、同じメモリ位置に配置されます。

これは、何が起こっているかを非常に明確に示しています(Pythonの他の実装では出力が異なる可能性があります)。

class A:
    def __init__(self): print("a")
    def __del__(self): print("b")

# a a b b False
print(A() is A())
# a b a b True
print(id(A()) == id(A()))
于 2010-10-06T22:08:54.843 に答える
-6

リストとdictの==演算子は、オブジェクトIDを比較して、それらが同じオブジェクトであるかどうかを確認しませんobj1 is obj2。そのために使用します。

代わりに、==演算子は、dictのリストのメンバーを比較して、それらが同じであるかどうかを確認します。

于 2010-10-06T22:08:34.567 に答える