Dostęp Do Adresu Pamięci Obiektu
Kiedy wywołujesz metodę object.__repr__()
w Pythonie otrzymujesz coś takiego z powrotem:
Main .Obiekt testowy przy 0x2aba1c0cf890 >
Czy Jest jakiś sposób, aby utrzymać adres pamięci, jeśli przeciążasz __repr__()
, a następnie wywołujesz super(Class, obj).__repr__()
i regexujesz go?
8 answers
Instrukcja Pythona ma to do powiedzenia o id()
:
Zwraca "tożsamość" obiektu. Jest to liczba całkowita (lub długa liczba całkowita) które gwarantują wyjątkowość i stała dla tego obiektu podczas jego całe życie. Dwa obiekty z nie nakładające się na siebie życia mogą mieć ta sama wartość id (). (Nota wdrożeniowa: to jest adres obiektu.)
Więc w Cpythonie będzie to adres obiektu. Brak takiej gwarancji dla innych Pythonów Tłumacz.
Zauważ, że jeśli piszesz rozszerzenie C, masz pełny dostęp do wewnętrznych interpreterów Pythona, w tym dostęp do adresów obiektów bezpośrednio.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-28 07:21:02
Możesz ponownie zaimplementować domyślny repr w ten sposób:
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 15:32:16
Po prostu użyj
id(object)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 14:37:24
Jest tu kilka kwestii, które nie są objęte żadną z innych odpowiedzi.
Pierwszy, id
tylko zwraca:
"tożsamość" przedmiotu. Jest to liczba całkowita (lub długa liczba całkowita), która jest gwarantowana jako unikalna i stała dla tego obiektu podczas jego życia. Dwa obiekty, które nie nakładają się na siebie, mogą mieć tę samą wartość
id()
.
W Cpythonie jest to wskaźnik do PyObject
to reprezentuje obiekt w interpreterze, który jest tą samą rzeczą, którą wyświetla object.__repr__
. Ale to tylko szczegóły implementacji CPython, a nie coś, co jest prawdziwe w Pythonie w ogóle. Jython nie zajmuje się wskaźnikami, zajmuje się referencjami Javy (które JVM oczywiście reprezentuje jako wskaźniki, ale nie możesz ich zobaczyć-i nie chciałbyś, ponieważ GC może je przesuwać). PyPy pozwala różnym typom mieć różne rodzaje id
, ale najbardziej ogólnym jest tylko Indeks do tabeli obiekty, na których wywołałeś id
, co oczywiście nie będzie wskaźnikiem. Nie jestem pewien co do IronPython, ale podejrzewałbym, że bardziej przypomina Jython niż CPython pod tym względem. Tak więc, w większości implementacji Pythona, nie ma sposobu, aby uzyskać to, co pojawiło się w tym repr
, i nie ma sensu, jeśli to zrobiłeś.
A jeśli zależy Ci tylko na Cpythonie? W końcu to dość powszechna sprawa.
Cóż, po pierwsze, możesz zauważyć, że id
jest liczbą całkowitą;* jeśli chcesz, aby 0x2aba1c0cf890
string zamiast numeru 46978822895760
, będziesz musiał sam sformatować. Pod okładkami, wierzę, że object.__repr__
ostatecznie używa printf
' S %p
format, którego nie masz z Pythona... ale zawsze możesz to zrobić:
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
* W 3.x, to int
. W 2.x, to int
, jeśli jest wystarczająco duży, aby trzymać wskaźnik-co może nie być spowodowane problemami z numerami podpisanymi na niektórych platformach - i long
w przeciwnym razie.
Czy jest coś, co można zrobić z tymi wskaźnikami oprócz wydrukować? Pewnie (znowu zakładając, że zależy Ci tylko na Cpythonie).
Wszystkie funkcje C API przyjmują wskaźnik do PyObject
lub pokrewnego typu. Dla tych powiązanych typów, możesz po prostu wywołać PyFoo_Check
, aby upewnić się, że naprawdę jest to obiekt Foo
, a następnie rzucić za pomocą (PyFoo *)p
. Tak więc, jeśli piszesz rozszerzenie C, id
jest dokładnie tym, czego potrzebujesz.
A jeśli piszesz czysty kod Pythona? Możesz wywoływać dokładnie te same funkcje za pomocą pythonapi
od ctypes
.
Wreszcie kilka innych odpowiedzi poruszyło ctypes.addressof
. To nie ma tu znaczenia. To działa tylko dla ctypes
obiektów, takich jak c_int32
(i może kilku obiektów przypominających bufor pamięci, takich jak te dostarczone przez numpy
). I nawet tam, nie daje Ci adresu c_int32
, tylko adres poziomu C int32
, który c_int32
kończy się.
To jest powiedziane, częściej niż nie, jeśli naprawdę uważasz, że potrzebujesz adres coś, w pierwszej kolejności nie chciałeś natywnego obiektu Pythona, chciałeś obiekt ctypes
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-09 18:41:51
Tylko w odpowiedzi na Torstena, nie byłem w stanie wywołać addressof()
na zwykłym obiekcie Pythona. Ponadto id(a) != addressof(a)
. To jest w CPython, Nie wiem o niczym innym.
>>> 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-07 17:14:04
Z ctypes , możesz osiągnąć to samo z
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
Dokumentacja:
addressof(C instance) -> integer
Zwraca adres wewnętrznego bufora instancji C
Zauważ, że w Cpythonie, aktualnie id(a) == ctypes.addressof(a)
, ale ctypes.addressof
powinien zwracać prawdziwy adres dla każdej implementacji Pythona, Jeśli
- ctypes jest obsługiwany
- wskaźniki pamięci są poprawnym pojęciem.
Edit : dodano informację o interpreterze-niezależność od ctypes
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 15:00:58
Możesz uzyskać coś odpowiedniego do tego celu za pomocą:
id(self)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 14:38:01
Chociaż prawdą jest, że id(object)
pobiera adres obiektu w domyślnej implementacji CPython, jest to generalnie bezużyteczne... nie możesz zrobić niczego z adresem z czystego kodu Pythona.
Jedyny raz, kiedy będziesz mógł użyć tego adresu, to z biblioteki rozszerzeń C... w takim przypadku uzyskanie adresu obiektu jest trywialne, ponieważ obiekty Pythona są zawsze przekazywane jako wskaźniki C.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 16:10:37