Yanıtlar:
Python kılavuzu hakkında şöyle demektedir id()
:
Bir nesnenin "kimliğini" döndür. Bu, yaşamı boyunca bu nesne için benzersiz ve sabit olması garanti edilen bir tamsayıdır (veya uzun tamsayıdır) Üst üste binmeyen ömürleri olan iki nesne aynı id () değerine sahip olabilir. (Uygulama notu: bu nesnenin adresidir.)
CPython'da bu, nesnenin adresi olacaktır. Yine de, diğer Python tercümanları için böyle bir garanti yoktur.
Bir C uzantısı yazıyorsanız, doğrudan nesnelerin adreslerine erişim de dahil olmak üzere Python yorumlayıcısının içlerine tam erişiminiz olduğunu unutmayın.
lifetime
(ve ömür boyu ne anlama geldiği) ne anlama gelir overlap/not overlap
?
Varsayılan repr'i şu şekilde yeniden uygulayabilirsiniz:
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
return object.__repr__(self)
yapabilirsiniz, hatta yapabilirsinizobject.__repr__(obj)
__repr__ = object.__repr__
ve neredeyse işe yaramaz, çünkü bunun işe yaramadığı çeşitli durumlar vardır, örneğin __getattribute__
kimliğin geçersiz kılınması veya CPython olmayan bir uygulama bellek konumu. Ayrıca z-doldurmaz, bu nedenle sistem 64bit ise ve sıfırları gerektiği gibi eklemeniz gerekir.
Sadece kullan
id(object)
id()
@JLT
Burada, diğer yanıtların hiçbirinde ele alınmayan birkaç sorun var.
İlk olarak, id
yalnızca şunu döndürür:
bir nesnenin “kimliği”. Bu, ömrü boyunca bu nesne için benzersiz ve sabit olduğu garanti edilen bir tam sayıdır (veya uzun tam sayıdır). Örtüşmeyen ömürleri olan iki nesne aynı
id()
değere sahip olabilir .
CPython'da, bu PyObject
, yorumlayıcıda object.__repr__
görüntülenen aynı şey olan nesneyi temsil eden öğeye işaretçi olur . Ancak bu sadece CPython'un bir uygulama detayıdır, genel olarak Python için geçerli olan bir şey değildir. Jython işaretçilerle ilgilenmez, Java referanslarıyla ilgilenir (ki JVM muhtemelen işaretçiler olarak temsil edilir, ancak bunları göremezsiniz - ve istemezsiniz, çünkü GC onları hareket ettirebilir). PyPy, farklı türlerin farklı türlere sahip olmasına izin verir id
, ancak en genel olanı, aradığınız nesne tablosuna sadece bir endekstirid
, ki bu açıkça bir işaretçi olmayacaktır. IronPython hakkında emin değilim, ama bu konuda CPython gibi Jython gibi daha fazla şüpheliydim. Yani, çoğu Python uygulamasında, bu konuda ne ortaya çıktığını elde etmenin bir yolu repr
yoktur ve eğer yaptıysanız, hiçbir faydası yoktur.
Peki ya sadece CPython'u önemsiyorsanız? Ne de olsa bu oldukça yaygın bir durum.
İlk olarak, id
bunun bir tamsayı olduğunu fark edebilirsiniz ; * sayı 0x2aba1c0cf890
yerine bu dizeyi istiyorsanız, 46978822895760
kendiniz biçimlendirmeniz gerekecektir. Kapakları altında, inanıyorum object.__repr__
sonuçta kullanıyor printf
'ın %p
Eğer Python yok biçimi, ... ama her zaman bunu yapabilirsiniz:
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
* 3.x'te bu bir int
. 2.x'te, int
bir işaretçi tutacak kadar büyükse - bu bazı platformlarda imzalı sayı sorunları nedeniyle olmayabilir - long
aksi halde.
Bu işaretçilerle bunları yazdırmanın yanı sıra yapabileceğiniz bir şey var mı? Elbette (tekrar, sadece CPython'u önemsediğinizi varsayarsak).
Tüm C API işlevleri bir PyObject
veya ilgili türe işaretçi olur . Bu türler için, PyFoo_Check
bunun gerçekten bir Foo
nesne olduğundan emin olmak için çağırabilir , sonra ile yayınlayabilirsiniz (PyFoo *)p
. Yani, bir C uzantısı yazıyorsanız id
, tam olarak ihtiyacınız olan şeydir.
Saf Python kodu yazıyorsanız ne olacak? Sen aynı şeyi aynı işlevleri çağırabilir pythonapi
dan ctypes
.
Sonunda, diğer cevaplardan birkaçı gündeme geldi ctypes.addressof
. Burada önemli değil. Bu sadece ctypes
gibi nesneler c_int32
(ve belki de sağladıkları gibi birkaç bellek arabelleği benzeri nesne numpy
) için çalışır. Ve, orada bile, size adresini vermiyor c_int32
size C düzeyinde adresini veriyor, değer int32
o c_int32
tamamladı.
Bununla birlikte, bir şeyin adresine gerçekten ihtiyacınız olduğunu düşünüyorsanız, ilk etapta yerel bir Python nesnesi istemediniz, bir ctypes
nesne istediniz .
id
bir de kesilebilir değerleri tutmak için kullanır dahil- seen
ya bir cache
dict-yok üzerinde herhangi bir şekilde bağlıdır id
bir işaretçi olarak, ya da herhangi bir şekilde benzer repr
. Tam da bu yüzden bu kod sadece CPython'da çalışmak yerine tüm Python uygulamalarında çalışır.
id
, ama hala java'da bile nesnenin adresini alabilirsin, garip görünüyor (C) Python'da bir yol yok çünkü birisinin hareket etmeyecek sabit gc'si var, böylece adres aynı kalıyor
id
bir nesne olsun, olmasın, bir adres olsun ya da olmasın. Örneğin, PyPy'de, id
genellikle uygulamadaki bazı gizli tablolara bir dizin olmasına rağmen, CPython'daki bir anahtar kadar yararlıdır, ancak bir işaretçi işe yaramaz, çünkü (Java gibi) nesne taşınabilir hafıza.
id
, bir nesneye ait nesnenin bellekteki konumunun işaretçisi olduğunu uygulamaya özel bir ayrıntı olarak açık bir şekilde belgelemektedir . Bu nedenle, CPython'a özgü kodda işaretçi değeri (yanıtta da açıklandığı gibi neredeyse hiç yapmadığınız) için herhangi bir kullanımınız varsa, belgeyi almanın ve çalışmayı garanti etmenin bir yolu vardır.
Torsten'e yanıt olarak, addressof()
normal bir python nesnesini çağıramıyordum. Ayrıca id(a) != addressof(a)
,. Bu CPython'da, başka bir şey bilmiyorum.
>>> 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 ile aynı şeyi elde edebilirsiniz
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
Belgeler:
addressof(C instance) -> integer
C örneği dahili arabelleğinin adresini döndürme
CPython içinde, şu anda unutmayın id(a) == ctypes.addressof(a)
, ancak ctypes.addressof
eğer her Python uygulaması için gerçek adresini dönmelidir
Edit : ctypes tercüman bağımsızlığı hakkında bilgi eklendi
TypeError: invalid type
Python 3.4 ile denediğimde ortaya çıkıyor.
Bu amaç için uygun bir şey elde edebilirsiniz:
id(self)
Bu eski bir soru olduğunu biliyorum ama hala programlıyorsanız, bugünlerde python 3 ... Aslında bir dize ise, o zaman bunu yapmak için gerçekten kolay bir yol olduğunu buldum:
>>> spam.upper
<built-in method upper of str object at 0x1042e4830>
>>> spam.upper()
'YO I NEED HELP!'
>>> id(spam)
4365109296
dize dönüştürme de bellekteki konumu etkilemez:
>>> spam = {437 : 'passphrase'}
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
>>> str(spam)
"{437: 'passphrase'}"
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
id(object)
Varsayılan CPython uygulamasında nesnenin adresini aldığı doğru olsa da , bu genellikle işe yaramaz ... saf Python kodundan adresle hiçbir şey yapamazsınız .
Adresi gerçekten kullanabileceğiniz tek zaman bir C uzantısı kitaplığından ... bu durumda Python nesneleri her zaman C işaretçisi olarak iletildiği için nesnenin adresini almak önemsizdir.
ctypes
Standart Kitaplıktaki yerleşik araç setini kullanmadığınız sürece . Bu durumda adres ile her türlü şeyi yapabilirsiniz :)