Pergunta

Quando você chamar o método object.__repr__() em Python que você começa algo como isso de volta:

<__main__.Test object at 0x2aba1c0cf890> 

Existe alguma maneira de obter um porão do endereço de memória, se você sobrecarregar __repr__(), outra super(Class, obj).__repr__() seguida, chamar e regexing-lo?

Foi útil?

Solução

O Python manual do tem a dizer sobre id():

Voltar a "identidade '' de um objeto. Este é um inteiro (ou inteiro longo) que é garantido para ser único e constante para este objecto, durante a sua tempo de vida. Dois objetos com tempo de vida sem sobreposição pode ter o mesmo id () valor. (Execução nota: este é o endereço do objeto.)

Assim, em CPython, este será o endereço do objeto. Sem essa garantia para qualquer outro interpretador Python, no entanto.

Note que se você estiver escrevendo uma extensão C, você tem acesso total aos componentes internos do interpretador Python, incluindo o acesso aos endereços dos objetos diretamente.

Outras dicas

Você pode reimplementar o padrão repr desta maneira:

def __repr__(self):
    return '<%s.%s object at %s>' % (
        self.__class__.__module__,
        self.__class__.__name__,
        hex(id(self))
    )

Apenas uso

id(object)

Existem algumas questões aqui que não são abrangidos por qualquer das outras respostas.

Em primeiro lugar, id apenas retornos:

a “identidade” de um objeto. Este é um inteiro (ou inteiro longo), que está garantido para ser única e constante para este objecto, durante a sua vida útil. Dois objetos com não-sobreposição vidas podem ter o mesmo valor id().


Em CPython, este passa a ser o ponteiro para a PyObject que representa o objeto no interpretador, que é a mesma coisa que object.__repr__ monitores. Mas este é apenas um detalhe de implementação de CPython, e não algo que é verdade para Python em geral. não Jython não tratam de ponteiros, trata-se em referências Java (que a JVM é claro provavelmente representa como ponteiros, mas você não pode ver os e não iria querer, porque o GC é permitido para movê-los). PyPy permite que diferentes tipos têm diferentes tipos de id, mas o mais geral é apenas um índice em uma tabela de objetos que você chamou id diante, o que, obviamente, não vai ser um ponteiro. Eu não tenho certeza sobre IronPython, mas eu suspeito que é mais como Jython que como CPython a este respeito. Assim, na maioria das implementações de Python, não há nenhuma maneira de conseguir tudo o que apareceu em que repr, e não adianta se você fez.


Mas e se você só se preocupam com CPython? Isso é um caso muito comum, afinal.

Bem, em primeiro lugar, você pode perceber que id é um inteiro; * se você quiser essa seqüência 0x2aba1c0cf890 em vez do número 46978822895760, você vai ter que formatá-lo a si mesmo. Debaixo das cobertas, acredito object.__repr__ é em última análise, usando o formato printf de %p, que você não tem de Python ... mas você sempre pode fazer isso:

format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')

* Em 3.x, é uma int. Em 2.x, é uma int se que é grande o suficiente para armazenar um ponteiro-que é não pode ser por causa de problemas números assinados em algumas plataformas-e uma long de outra forma.

Existe alguma coisa que você pode fazer com esses ponteiros além de imprimi-los? Claro que (novamente, supondo que você só se preocupam com CPython).

Todos os C funções API tomar um ponteiro para uma PyObject ou um tipo relacionado. Para os tipos relacionados, você pode apenas chamar PyFoo_Check para se certificar de que realmente é um objeto Foo, em seguida, lançar com (PyFoo *)p. Então, se você está escrevendo uma extensão C, o id é exatamente o que você precisa.

E se você está escrevendo código Python puro? Você pode chamar o exato mesmas funções com pythonapi partir ctypes.


Finalmente, algumas das outras respostas trouxeram até ctypes.addressof . Isso não é relevante aqui. Isso só funciona para objetos ctypes como c_int32 (e talvez um pouco de memória-tampão-como objetos, como aqueles fornecidos pelo numpy). E, mesmo aí, não é o que lhe dá o endereço do valor c_int32, é o que lhe dá o endereço do int32 de nível C que o c_int32 embrulha-se.

Dito isto, mais frequentemente do que não, se você realmente acha que precisa o endereço de alguma coisa, você não quer um objeto Python nativa, em primeiro lugar, você queria um objeto ctypes.

Apenas em resposta a Torsten, eu não era capaz de chamar addressof() em um objeto python regular. Além disso, id(a) != addressof(a). Isto está em CPython, não sei sobre qualquer outra coisa.

>>> 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 da memória intermédia interna exemplo C

Note que em CPython, atualmente id(a) == ctypes.addressof(a), mas ctypes.addressof deve retornar o endereço real para cada implementação de Python, se

  • ctypes é suportado
  • ponteiros de memória são uma noção válido.

Editar : informação adicional sobre o intérprete-independência do ctypes

Você pode obter algo adequado para o efeito com:

id(self)

Embora seja verdade que id(object) obtém o endereço do objeto na implementação CPython padrão, essa é geralmente inútil ... você não pode do qualquer coisa com o endereço a partir do código Python puro.

A única vez que você realmente ser capaz de usar o endereço é de uma biblioteca de extensão C ... caso em que é trivial para obter o endereço do objeto desde objetos Python são sempre passados ??em torno de como ponteiros C.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top