Pythonでメソッドを呼び出すと、次のobject.__repr__()
ようなものが返されます。
<__main__.Test object at 0x2aba1c0cf890>
をオーバーロードした場合にメモリアドレスを取得する方法はありますか?それ__repr__()
以外に、それを呼び出しsuper(Class, obj).__repr__()
て正規表現しますか?
Pythonでメソッドを呼び出すと、次のobject.__repr__()
ようなものが返されます。
<__main__.Test object at 0x2aba1c0cf890>
をオーバーロードした場合にメモリアドレスを取得する方法はありますか?それ__repr__()
以外に、それを呼び出しsuper(Class, obj).__repr__()
て正規表現しますか?
Pythonのマニュアルには、次のように書かれていid()
ます。
オブジェクトの「ID」を返します。これは、このオブジェクトの有効期間中、一意で一定であることが保証されている整数 (または倍長整数) です。有効期間が重複しない 2 つのオブジェクトは、同じ id() 値を持つ場合があります。 (実装上の注意: これはオブジェクトのアドレスです。)
したがって、CPython では、これがオブジェクトのアドレスになります。ただし、他の Python インタープリターではそのような保証はありません。
C 拡張機能を作成している場合は、オブジェクトのアドレスへの直接アクセスを含め、Python インタープリターの内部に完全にアクセスできることに注意してください。
デフォルトの repr を次のように再実装できます。
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
使うだけ
id(object)
ここには、他の回答ではカバーされていない問題がいくつかあります。
まず、id
以下のみを返します。
オブジェクトの「アイデンティティ」。これは、このオブジェクトの有効期間中に一意で一定であることが保証されている整数 (または長整数) です。有効期間が重複しない 2 つのオブジェクトは、同じ
id()
値を持つ場合があります。
CPython では、これはたまたまPyObject
インタプリタ内のオブジェクトを表すへのポインタであり、object.__repr__
表示されるものと同じです。しかし、これは CPython の実装の詳細に過ぎず、一般的な Python に当てはまるものではありません。Jython はポインターを処理しません。Java 参照を処理します (もちろん、JVM はおそらくポインターとして表しますが、それらを表示することはできません。また、GC がポインターを移動できるため、そうしたくないでしょう)。PyPy では、さまざまな型でさまざまな種類の を使用できますid
が、最も一般的なのは、呼び出したオブジェクトのテーブルへの単なるインデックスです。id
これは明らかにポインタにはなりません。IronPython についてはよくわかりませんが、この点では CPython よりも Jython に似ているのではないかと思います。そのため、ほとんどの Python 実装では、その に表示されたものを取得する方法はなく、取得しても意味がrepr
ありません。
しかし、CPython だけに関心がある場合はどうでしょうか? 結局のところ、それはかなり一般的なケースです。
id
まず、 が整数であることに気付くかもしれません。* 0x2aba1c0cf890
number の代わりにその文字列が必要な場合46978822895760
は、自分でフォーマットする必要があります。裏では、object.__repr__
最終的にはprintf
の%p
形式を使用していると思いますが、これは Python にはありませんが、いつでもこれを行うことができます。
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
* 3.x では、int
. 2.x では、int
ポインターを保持するのに十分な大きさの場合 (一部のプラットフォームでの符号付き数値の問題が原因ではない可能性があります) とlong
そうでない場合です。
印刷する以外に、これらのポインターでできることはありますか? 確かに (繰り返しますが、CPython だけに関心があると仮定すると)。
すべてのC APIPyObject
関数は、または関連する型へのポインターを取ります。PyFoo_Check
これらの関連する型については、それが本当にオブジェクトであることを確認するために呼び出してからFoo
、 でキャストでき(PyFoo *)p
ます。したがって、C 拡張機能を作成している場合id
は、まさに必要なものです。
純粋な Python コードを書いている場合はどうでしょうか? pythonapi
fromでまったく同じ関数を呼び出すことができますctypes
。
最後に、他のいくつかの回答が持ち上がりましたctypes.addressof
。それはここでは関係ありません。これは、 のようなオブジェクト(および によって提供されるようないくつかのメモリ バッファのようなオブジェクト)に対してのみ機能しctypes
ます。さらに、値のアドレスを提供するのではなく、C レベルのアドレスを提供します。c_int32
numpy
c_int32
int32
c_int32
そうは言っても、多くの場合、何かのアドレスが本当に必要だと思う場合は、そもそもネイティブの Python オブジェクトが必要ではなく、オブジェクトが必要でしたctypes
。
Torsten に応えてaddressof()
、通常の Python オブジェクトを呼び出すことができませんでした。さらに、id(a) != addressof(a)
. これは CPython にあり、他については知りません。
>>> from ctypes import c_int, addressof
>>> a = 69
>>> addressof(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: invalid type
>>> b = c_int(69)
>>> addressof(b)
4300673472
>>> id(b)
4300673392
ctypesを使用すると、同じことを実現できます
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
ドキュメンテーション:
addressof(C instance) -> integer
C インスタンスの内部バッファのアドレスを返します
CPython では、現在id(a) == ctypes.addressof(a)
、 がctypes.addressof
、各 Python 実装の実際のアドレスを返す必要があることに注意してください。
編集:ctypesのインタプリタ非依存に関する情報を追加
その目的に適したものを次の方法で取得できます。
id(self)
デフォルトの CPython 実装でオブジェクトのアドレスを取得するのは事実ですが、これは一般的に役に立ちません...純粋な Python コードからのアドレスでは何もid(object)
できません。
実際にアドレスを使用できるのは、C 拡張ライブラリからの場合だけです...この場合、Python オブジェクトは常に C ポインターとして渡されるため、オブジェクトのアドレスを取得するのは簡単です。