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 todaoverlap/not overlap
) se refere nesse contexto?Você pode reimplementar o repr padrão da seguinte maneira:
fonte
return object.__repr__(self)
ou até mesmo fazerobject.__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
fonte
id()
@JLTExistem alguns problemas aqui que não são cobertos por nenhuma das outras respostas.
Primeiro,
id
apenas retorna: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 diferentesid
, 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 essa0x2aba1c0cf890
sequência em vez do número46978822895760
, precisará formatá-la. Nos bastidores, acredito que, emobject.__repr__
última análise, esteja usandoprintf
o%p
formato s , que você não possui do Python ... mas você sempre pode fazer isso:* No 3.x, é um
int
. Na 2.x, é umint
tamanho suficiente para armazenar um ponteiro - o que pode não ser por causa de problemas com números assinados em algumas plataformas - e delong
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 ligarPyFoo_Check
para garantir que realmente seja umFoo
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
fromctypes
.Finalmente, algumas das outras respostas foram levantadas
ctypes.addressof
. Isso não é relevante aqui. Isso funciona apenas paractypes
objetos comoc_int32
(e talvez alguns objetos semelhantes a buffer de memória, como os fornecidos pornumpy
). E, mesmo lá, não está fornecendo o endereço doc_int32
valor, está fornecendo o endereço do nível Cint32
quec_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.fonte
id
- incluindo usá-los para manter valores mutáveis em umseen
conjunto ou em umcache
ditado - não dependem de maneira alguma deid
ser um ponteiro ou de qualquer maneira relacionados aorepr
. É 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 mesmoid
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 dissoid(a) != addressof(a)
,. Isso está no CPython, não sei de mais nada.fonte
Com ctypes , você pode conseguir a mesma coisa com
Documentação:
Observe que no CPython, atualmente
id(a) == ctypes.addressof(a)
, masctypes.addressof
deve retornar o endereço real para cada implementação do Python, seEditar : informações adicionadas sobre a independência de intérpretes de ctypes
fonte
TypeError: invalid type
quando o tento com o Python 3.4.Você pode obter algo adequado para esse fim com:
fonte
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:
A conversão de cadeia de caracteres não afeta o local na memória:
fonte
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.
fonte
ctypes
kit de ferramentas interno na Biblioteca Padrão. Caso em que você pode fazer todos os tipos de coisas com o endereço :)