206

Pythonでメソッドを呼び出すと、次のobject.__repr__()ようなものが返されます。

<__main__.Test object at 0x2aba1c0cf890> 

をオーバーロードした場合にメモリアドレスを取得する方法はありますか?それ__repr__()以外に、それを呼び出しsuper(Class, obj).__repr__()て正規表現しますか?

4

11 に答える 11

240

Pythonのマニュアルには、次のように書かれていid()ます。

オブジェクトの「ID」を返します。これは、このオブジェクトの有効期間中、一意で一定であることが保証されている整数 (または倍長整数) です。有効期間が重複しない 2 つのオブジェクトは、同じ id() 値を持つ場合があります。 (実装上の注意: これはオブジェクトのアドレスです。)

したがって、CPython では、これがオブジェクトのアドレスになります。ただし、他の Python インタープリターではそのような保証はありません。

C 拡張機能を作成している場合は、オブジェクトのアドレスへの直接アクセスを含め、Python インタープリターの内部に完全にアクセスできることに注意してください。

于 2008-09-23T14:41:30.270 に答える
82

デフォルトの repr を次のように再実装できます。

def __repr__(self):
    return '<%s.%s object at %s>' % (
        self.__class__.__module__,
        self.__class__.__name__,
        hex(id(self))
    )
于 2008-09-23T14:49:57.553 に答える
62

使うだけ

id(object)
于 2008-09-23T14:37:24.853 に答える
29

ここには、他の回答ではカバーされていない問題がいくつかあります。

まず、id以下のみを返します。

オブジェクトの「アイデンティティ」。これは、このオブジェクトの有効期間中に一意で一定であることが保証されている整数 (または長整数) です。有効期間が重複しない 2 つのオブジェクトは、同じid()値を持つ場合があります。


CPython では、これはたまたまPyObjectインタプリタ内のオブジェクトを表すへのポインタであり、object.__repr__表示されるものと同じです。しかし、これは CPython の実装の詳細に過ぎず、一般的な Python に当てはまるものではありません。Jython はポインターを処理しません。Java 参照を処理します (もちろん、JVM はおそらくポインターとして表しますが、それらを表示することはできません。また、GC がポインターを移動できるため、そうしたくないでしょう)。PyPy では、さまざまな型でさまざまな種類の を使用できますidが、最も一般的なのは、呼び出したオブジェクトのテーブルへの単なるインデックスです。idこれは明らかにポインタにはなりません。IronPython についてはよくわかりませんが、この点では CPython よりも Jython に似ているのではないかと思います。そのため、ほとんどの Python 実装では、その に表示されたものを取得する方法はなく、取得しても意味がreprありません。


しかし、CPython だけに関心がある場合はどうでしょうか? 結局のところ、それはかなり一般的なケースです。

idまず、 が整数であることに気付くかもしれません。* 0x2aba1c0cf890number の代わりにその文字列が必要な場合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 コードを書いている場合はどうでしょうか? pythonapifromでまったく同じ関数を呼び出すことができますctypes


最後に、他のいくつかの回答が持ち上がりましたctypes.addressof。それはここでは関係ありません。これは、 のようなオブジェクト(および によって提供されるようないくつかのメモリ バッファのようなオブジェクト)に対してのみ機能しctypesます。さらに、値のアドレスを提供するのではなく、C レベルのアドレスを提供します。c_int32numpyc_int32int32c_int32

そうは言っても、多くの場合、何かのアドレスが本当に必要だと思う場合は、そもそもネイティブの Python オブジェクトが必要ではなく、オブジェクトが必要でしたctypes

于 2014-10-09T18:41:51.540 に答える
14

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
于 2011-01-07T17:14:04.557 に答える
4

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 がサポートされています
  • メモリ ポインタは有効な概念です。

編集:ctypesのインタプリタ非依存に関する情報を追加

于 2008-09-23T15:00:58.150 に答える
3

その目的に適したものを次の方法で取得できます。

id(self)
于 2008-09-23T14:38:01.760 に答える
0

デフォルトの CPython 実装でオブジェクトのアドレスを取得するのは事実ですが、これは一般的に役に立ちません...純粋な Python コードからのアドレスでは何もid(object)できません。

実際にアドレスを使用できるのは、C 拡張ライブラリからの場合だけです...この場合、Python オブジェクトは常に C ポインターとして渡されるため、オブジェクトのアドレスを取得するのは簡単です。

于 2008-09-23T16:10:37.110 に答える