The pengguna Python telah mengatakan tentang id()
:
Kembalikan "identitas" suatu objek. Ini adalah bilangan bulat (atau bilangan bulat panjang) yang dijamin unik dan konstan untuk objek ini selama masa pakainya. Dua objek dengan masa hidup yang tidak tumpang tindih mungkin memiliki nilai id () yang sama. (Catatan Implementasi: ini adalah alamat objek.)
Jadi dalam CPython, ini akan menjadi alamat objek. Namun, tidak ada jaminan untuk interpreter Python lainnya.
Perhatikan bahwa jika Anda menulis ekstensi C, Anda memiliki akses penuh ke internal interpreter Python, termasuk akses ke alamat objek secara langsung.
lifetime
(dan apa artinya seumur hidupoverlap/not overlap
) dalam konteks ini?Anda dapat menerapkan ulang repr default dengan cara ini:
sumber
return object.__repr__(self)
atau bahkan hanya melakukanobject.__repr__(obj)
kapan pun Anda membutuhkan ini alih-alih membuat kelas baru__repr__ = object.__repr__
, dan bukan sebagai bukti bodoh, karena ada berbagai situasi di mana ini tidak berhasil, misalnya ditimpa__getattribute__
implementasi yang ditimpa atau non-CPython di mana id tidak lokasi memori. Itu juga tidak z-fill, jadi Anda harus bekerja jika sistemnya 64bit dan menambahkan angka nol seperlunya.Gunakan saja
sumber
id()
@JLT iniAda beberapa masalah di sini yang tidak dicakup oleh jawaban lain mana pun.
Pertama,
id
hanya mengembalikan:Dalam CPython, ini adalah penunjuk ke
PyObject
yang mewakili objek dalam penafsir, yang merupakan hal yang sama yangobject.__repr__
ditampilkan. Tapi ini hanyalah detail implementasi dari CPython, bukan sesuatu yang berlaku untuk Python secara umum. Jython tidak berurusan dengan pointer, ia berurusan dengan referensi Java (yang tentu saja mewakili JVM sebagai pointer, tetapi Anda tidak dapat melihat itu — dan tidak mau, karena GC diizinkan untuk memindahkannya). PyPy memungkinkan berbagai jenis memiliki jenis yang berbedaid
, tetapi yang paling umum hanyalah indeks ke dalam tabel objek yang Anda panggilid
pada, yang jelas tidak akan menjadi penunjuk. Saya tidak yakin tentang IronPython, tapi saya menduga ini lebih seperti Jython daripada seperti CPython dalam hal ini. Jadi, di sebagian besar implementasi Python, tidak ada cara untuk mendapatkan apa pun yang muncul dalam hal iturepr
, dan tidak ada gunanya jika Anda melakukannya.Tetapi bagaimana jika Anda hanya peduli tentang CPython? Bagaimanapun, itu adalah kasus yang cukup umum.
Nah, pertama, Anda mungkin melihat itu
id
adalah bilangan bulat; * jika Anda menginginkan0x2aba1c0cf890
string itu alih-alih nomornya46978822895760
, Anda harus memformatnya sendiri. Di bawah selimut, saya percayaobject.__repr__
akhirnya menggunakanprintf
's%p
format, yang Anda tidak memiliki dari Python ... tapi Anda selalu dapat melakukan hal ini:* Dalam 3.x, ini adalah
int
. Dalam 2.x, itu adalahint
jika itu cukup besar untuk memegang pointer — yang mungkin bukan karena masalah nomor yang ditandatangani pada beberapa platform — danlong
sebaliknya.Apakah ada yang bisa Anda lakukan dengan petunjuk ini selain mencetaknya? Tentu (sekali lagi, anggap Anda hanya peduli tentang CPython).
Semua fungsi C API mengambil pointer ke tipe
PyObject
atau yang terkait. Untuk jenis terkait, Anda bisa meneleponPyFoo_Check
untuk memastikan itu benar-benarFoo
objek, lalu dilemparkan dengan(PyFoo *)p
. Jadi, jika Anda menulis ekstensi C,id
itulah yang Anda butuhkan.Bagaimana jika Anda sedang menulis kode Python murni? Anda dapat memanggil fungsi yang sama persis dengan
pythonapi
darictypes
.Akhirnya, beberapa jawaban lain muncul
ctypes.addressof
. Itu tidak relevan di sini. Ini hanya berfungsi untukctypes
objek sepertic_int32
(dan mungkin beberapa objek seperti buffer memori, seperti yang disediakan olehnumpy
). Dan, bahkan di sana, itu tidak memberi Anda alamatc_int32
nilai, itu memberi Anda alamat tingkat-Cint32
yangc_int32
dirangkum.Yang sedang berkata, lebih sering daripada tidak, jika Anda benar-benar berpikir Anda perlu alamat sesuatu, Anda tidak ingin objek Python asli di tempat pertama, Anda menginginkan
ctypes
objek.sumber
id
— termasuk menggunakannya untuk menyimpan nilai yang bisa berubah dalam satuseen
set ataucache
dict — tidak bergantung pada cara apa punid
menjadi penunjuk, atau terkait dengan cara apa pun denganrepr
. Itulah sebabnya kode tersebut bekerja di semua implementasi Python, bukan hanya bekerja di CPython.id
untuk itu, tapi maksud saya masih bahkan di java Anda bisa mendapatkan alamat objek, tampaknya aneh tidak ada cara (C) Python karena yang benar-benar stabil gc yang tidak akan memindahkan objek sehingga alamat tetap samaid
objek itu, apakah itu alamat atau bukan. Misalnya, dalam PyPy,id
masih sama bermanfaatnya dengan kunci pada CPython, meskipun biasanya hanya indeks ke beberapa tabel tersembunyi dalam implementasi, tetapi sebuah pointer tidak akan berguna, karena (seperti Java) objek dapat dipindahkan dalam Penyimpanan.id
objek adalah pointer ke lokasi objek dalam memori. Jadi, jika Anda menggunakan nilai pointer (yang hampir tidak pernah Anda lakukan, seperti juga dijelaskan dalam jawaban) dalam kode khusus CPython, ada cara untuk mendapatkannya yang didokumentasikan dan dijamin berfungsi.Hanya untuk menanggapi Torsten, saya tidak dapat memanggil
addressof()
objek python biasa. Selanjutnyaid(a) != addressof(a)
,. Ini di CPython, tidak tahu tentang hal lain.sumber
Dengan ctypes , Anda dapat mencapai hal yang sama dengannya
Dokumentasi:
Perhatikan bahwa dalam CPython, saat ini
id(a) == ctypes.addressof(a)
, tetapictypes.addressof
harus mengembalikan alamat asli untuk setiap implementasi Python, jikaSunting : menambahkan informasi tentang independensi interpreter dari ctypes
sumber
TypeError: invalid type
ketika saya mencobanya dengan Python 3.4.Anda bisa mendapatkan sesuatu yang cocok untuk tujuan itu dengan:
sumber
Saya tahu ini adalah pertanyaan lama tetapi jika Anda masih memprogram, dalam python 3 hari ini ... Saya benar-benar menemukan bahwa jika itu adalah string, maka ada cara yang sangat mudah untuk melakukan ini:
konversi string tidak mempengaruhi lokasi dalam memori juga:
sumber
Meskipun benar bahwa
id(object)
mendapatkan alamat objek dalam implementasi CPython default, ini umumnya tidak berguna ... Anda tidak dapat melakukan apa pun dengan alamat dari kode Python murni.Satu-satunya waktu Anda benar-benar dapat menggunakan alamat adalah dari pustaka ekstensi C ... dalam hal ini sepele untuk mendapatkan alamat objek karena objek Python selalu dibagikan sebagai pointer C.
sumber
ctypes
toolkit bawaan di Perpustakaan Standar. Dalam hal ini Anda dapat melakukan segala macam hal dengan alamat :)