2016-11-30 4 views
1

少し驚くべき挙動。異なるモジュールで同じ名前の2つのクラスが同じ名前を共有します。異なるモジュールの同じ名前のクラスは、まったく同じ名前の文字列を共有しますか?

私はそれを本当に問題にすることはできませんが、誰もがなぜそれを知っていますか、それ以上の驚きの可能性はありますか?

デモ

>>> from a import a 
>>> from b import b 
>>> ta = a.Test() 
>>> tb = b.Test() 
>>> ta.__class__.__name__ 
'Test' 
>>> tb.__class__.__name__ 
'Test' 
>>> tb.__class__.__name__ is ta.__class__.__name__ # unexpected 
True 

>>> ta.__class__ 
<class 'a.a.Test'> 
>>> tb.__class__ 
<class 'b.b.Test'> 
+0

* "Pythonプログラムで使用される名前は自動的にインターンされます" * https://docs.python.org/3/library/sys.html#sys.intern – vaultah

+0

すべてのPython文字列は不変なので、文字列のインターン完全に安全です。 –

答えて

2

a/b/a/a.pyb/b.pyと空__init__.pyで)これはCPythonのインタプリタの実装の詳細です。

interns識別子文字列。ソースコード文字列に対しては1つのコピーしか作成されず、まったく同じ文字列値が表示されます。これは、辞書の包含テストをより速くする(ポインタ比較を最初に試みることによって)。

あなたは親切ノート sys.intern() function、使用して独自の文字列のためにこれを行うことができます

通常、Pythonプログラムで使用される名前が自動的に抑留されており、モジュール、クラス、またはインスタンスの属性を保持するために使用される辞書を鍵を保留している。

ホードが指摘したようにもAbout the changing id of a Python immutable string

+0

ありがとうございます。 Googleは有益思われる、これを見つけた:https://books.google.co.uk/books?id=mh0bU6NXrBgC&pg=PA505&lpg=PA505&dq=python+interns+identifiers&source=bl&ots=XznyDpc1hd&sig=fsNqflJ_l0N_UhlALvrPh3S7ETQ&hl=en&sa=X&ved=0ahUKEwj6kYP4udDQAhWlCcAKHTvgD_UQ6AEIKjAC#v= onepage&q = python%20interns%20identifiers&f = false – nigel222

+0

@ nigel222:その情報は古くなっています。私がリンクしている 'sys.intern()'のドキュメントを参照してください:* interned文字列は不滅*ではありません。あなたが持っているテキストは、それらがあると述べています。それらはPython 2.3までしか使用されていませんでした。 –

+0

はい、古いですが、 "interned"という言葉が意味することをより穏やかに説明しました!確かに、Python3内部のハッキングに対して信頼されないように! – nigel222

0

を参照してください - あなたは同じでオブジェクトを刺すに頼ることはできません - も、彼らは別のオブジェクトであることに。 (もちろん、同じ文字列を明示的に参照しない限り)。

名前を比較する場合は、==オブジェクトを使用してください。クラスが同じかどうかを知りたい場合は、is演算子を名前ではなくクラス自体に使用します。

+0

確かに。 'ta .__ class__はtb .__ class__です。 – nigel222

0

Pythonではすべてがオブジェクト/クラスです。あなたがクラスや関数のいずれを書いても、タイプはタイプです。

質問には2つのdiffクラスaとbがあります。ここでは、これらの2行が両方のクラスの2つのインスタンスを作成します。各オブジェクト戻りクラステスト

>>> ta = a.Test() 
>>> tb = b.Test() 

機能テスト。クラスを__class__に戻すと、オブジェクトタイプまたは__repr__オブジェクトが返されます。 の名前は、文字列形式のクラスのを返します。これを入力してタイプを確認する場合は、タイプ(tb。クラスの名前)を参照してください。 1 STRが他のタイプあるよう

>>> tb.__class__.__name__ is ta.__class__.__name__

これがtrueを返しています。

関連する問題