Respostas:
O manual do Python tem a dizer sobre id()
:
Retorne a "identidade" de um objeto. Este é um número inteiro (ou inteiro longo) que é garantido como único e constante para esse objeto durante sua vida útil. Dois objetos com vida útil não sobreposta podem ter o mesmo valor id (). (Nota de implementação: este é o endereço do objeto.)
Portanto, no CPython, este será o endereço do objeto. Porém, não existe essa garantia para qualquer outro intérprete Python.
Observe que, se você estiver escrevendo uma extensão C, terá acesso total aos componentes internos do interpretador Python, incluindo acesso diretamente aos endereços dos objetos.
lifetime
(e o que significa para a vida toda overlap/not overlap
) se refere nesse contexto?
Você pode reimplementar o repr padrão da seguinte maneira:
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
return object.__repr__(self)
ou até mesmo fazer object.__repr__(obj)
sempre que você precisar desta vez de fazer uma nova classe
__repr__ = object.__repr__
, e não é tão à prova de idiotas, pois há uma variedade de situações em que isso não funciona, por exemplo, uma __getattribute__
implementação substituída ou não CPython onde o ID não é a localização da memória. Ele também não é preenchido com z, então você teria que descobrir se o sistema é de 64 bits e adicionar os zeros conforme necessário.
Apenas use
id(object)
id()
@JLT
Existem alguns problemas aqui que não são cobertos por nenhuma das outras respostas.
Primeiro, id
apenas retorna:
a "identidade" de um objeto. Esse é um número inteiro (ou inteiro longo) que é garantido como único e constante para esse objeto durante sua vida útil. Dois objetos com vida útil sem sobreposição podem ter o mesmo
id()
valor.
No CPython, este é o ponteiro para o PyObject
que representa o objeto no intérprete, que é a mesma coisa que no, que obviamente não será um ponteiro. Não tenho certeza sobre o IronPython, mas eu suspeitaria que é mais como o Jython do que com o CPython a esse respeito. Portanto, na maioria das implementações do Python, não há como obter o que foi mostrado nisso , e de nada serve se você o fez.object.__repr__
exibida. Mas este é apenas um detalhe de implementação do CPython, não algo que é verdadeiro no Python em geral. O Jython não lida com ponteiros, lida com referências a Java (que a JVM provavelmente representa como ponteiros, mas você não pode vê-las - e não gostaria, porque o GC pode movê-las). O PyPy permite que tipos diferentes tenham tipos diferentes id
, mas o mais geral é apenas um índice em uma tabela de objetos que você chamouid
repr
Mas e se você se importa apenas com o CPython? Afinal, esse é um caso bastante comum.
Bem, primeiro, você pode perceber que id
é um número inteiro; * se você quiser essa 0x2aba1c0cf890
sequência em vez do número 46978822895760
, precisará formatá-la. Nos bastidores, acredito que, em object.__repr__
última análise, esteja usando printf
o %p
formato s , que você não possui do Python ... mas você sempre pode fazer isso:
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
* No 3.x, é um int
. Na 2.x, é um int
tamanho suficiente para armazenar um ponteiro - o que pode não ser por causa de problemas com números assinados em algumas plataformas - e de long
outra forma.
Há algo que você possa fazer com esses ponteiros além de imprimi-los? Claro (novamente, supondo que você se preocupe apenas com o CPython).
Todas as funções da API C levam um ponteiro para um PyObject
ou um tipo relacionado. Para esses tipos relacionados, você pode simplesmente ligar PyFoo_Check
para garantir que realmente seja um Foo
objeto e, em seguida, lançar com (PyFoo *)p
. Portanto, se você estiver escrevendo uma extensão C, id
é exatamente isso que você precisa.
E se você estiver escrevendo código Python puro? Você pode chamar exatamente as mesmas funções com pythonapi
from ctypes
.
Finalmente, algumas das outras respostas foram levantadas ctypes.addressof
. Isso não é relevante aqui. Isso funciona apenas para ctypes
objetos como c_int32
(e talvez alguns objetos semelhantes a buffer de memória, como os fornecidos por numpy
). E, mesmo lá, não está fornecendo o endereço do c_int32
valor, está fornecendo o endereço do nível C int32
que c_int32
envolve.
Dito isto, na maioria das vezes, se você realmente acha que precisa do endereço de algo, não queria um objeto Python nativo em primeiro lugar, queria um ctypes
objeto.
id
- incluindo usá-los para manter valores mutáveis em um seen
conjunto ou em um cache
ditado - não dependem de maneira alguma de id
ser um ponteiro ou de qualquer maneira relacionados ao repr
. É exatamente por isso que esse código funciona em todas as implementações do Python, em vez de apenas trabalhar no CPython.
id
para isso, mas quero dizer que, mesmo em java, você pode obter o endereço do objeto, parece estranho que não há como (C) Python, pois esse tem um gc realmente estável que não move objetos, portanto, o endereço permanece o mesmo
id
objeto para um objeto, seja ele um endereço ou não. Por exemplo, no PyPy, id
ainda é tão útil quanto uma chave no CPython, apesar de geralmente ser apenas um índice em alguma tabela oculta na implementação, mas um ponteiro seria inútil, porque (como Java) o objeto pode ser movido memória.
id
de um objeto é o ponteiro para o local do objeto na memória. Portanto, se você tiver alguma utilidade para o valor do ponteiro (o que você quase nunca faz, como também explicado na resposta) no código específico do CPython, existe uma maneira de obtê-lo documentado e garantido que funcione.
Em resposta a Torsten, não consegui chamar addressof()
um objeto python comum. Além disso id(a) != addressof(a)
,. Isso está no CPython, não sei de mais nada.
>>> 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
Com ctypes , você pode conseguir a mesma coisa com
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
Documentação:
addressof(C instance) -> integer
Retornar o endereço do buffer interno da instância C
Observe que no CPython, atualmente id(a) == ctypes.addressof(a)
, mas ctypes.addressof
deve retornar o endereço real para cada implementação do Python, se
Editar : informações adicionadas sobre a independência de intérpretes de ctypes
TypeError: invalid type
quando o tento com o Python 3.4.
Você pode obter algo adequado para esse fim com:
id(self)
Eu sei que essa é uma pergunta antiga, mas se você ainda estiver programando, no python 3 hoje em dia ... Na verdade, descobri que se for uma string, existe uma maneira muito fácil de fazer isso:
>>> spam.upper
<built-in method upper of str object at 0x1042e4830>
>>> spam.upper()
'YO I NEED HELP!'
>>> id(spam)
4365109296
A conversão de cadeia de caracteres não afeta o local na memória:
>>> spam = {437 : 'passphrase'}
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
>>> str(spam)
"{437: 'passphrase'}"
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
Embora seja verdade que id(object)
obtém o endereço do objeto na implementação padrão do CPython, isso geralmente é inútil ... você não pode fazer nada com o endereço do código Python puro.
A única vez em que você realmente poderia usar o endereço é de uma biblioteca de extensão C ... nesse caso, é trivial obter o endereço do objeto, pois os objetos Python sempre são passados como ponteiros C.
ctypes
kit de ferramentas interno na Biblioteca Padrão. Caso em que você pode fazer todos os tipos de coisas com o endereço :)