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, idyalnı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 repryoktur 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, idbunun bir tamsayı olduğunu fark edebilirsiniz ; * sayı 0x2aba1c0cf890yerine bu dizeyi istiyorsanız, 46978822895760kendiniz biçimlendirmeniz gerekecektir. Kapakları altında, inanıyorum object.__repr__sonuçta kullanıyor printf'ın %pEğ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, intbir işaretçi tutacak kadar büyükse - bu bazı platformlarda imzalı sayı sorunları nedeniyle olmayabilir - longaksi 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 PyObjectveya ilgili türe işaretçi olur . Bu türler için, PyFoo_Checkbunun gerçekten bir Foonesne 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 pythonapidan ctypes.
Sonunda, diğer cevaplardan birkaçı gündeme geldi ctypes.addressof. Burada önemli değil. Bu sadece ctypesgibi 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_int32size C düzeyinde adresini veriyor, değer int32o c_int32tamamladı.
Bununla birlikte, bir şeyin adresine gerçekten ihtiyacınız olduğunu düşünüyorsanız, ilk etapta yerel bir Python nesnesi istemediniz, bir ctypesnesne istediniz .
idbir de kesilebilir değerleri tutmak için kullanır dahil- seenya bir cachedict-yok üzerinde herhangi bir şekilde bağlıdır idbir 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
idbir nesne olsun, olmasın, bir adres olsun ya da olmasın. Örneğin, PyPy'de, idgenellikle 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.addressofeğer her Python uygulaması için gerçek adresini dönmelidir
Edit : ctypes tercüman bağımsızlığı hakkında bilgi eklendi
TypeError: invalid typePython 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.
ctypesStandart Kitaplıktaki yerleşik araç setini kullanmadığınız sürece . Bu durumda adres ile her türlü şeyi yapabilirsiniz :)