2009-09-08 5 views
83

내가 파이썬 객체의 ID를 가지고 있다고 가정 해 봅시다.이 객체는 id(thing)으로 검색했습니다. ID 번호로 다시 thing을 어떻게 찾을 수 있습니까?id()로 객체 가져 오기?

+0

저는 궁금합니다. 왜 이것을하고 싶습니까? 당신의 목표는 무엇입니까? –

+1

@Craig McQueen : http : // stackoverflow.com/questions/1400295/python-class-for-pickle-and-copy-persistent-object –

+0

이 소스를 다시 찾을 수는 없지만 id()가 반환하는 것은 특정 배포판에서 원하는 것이 무엇이든간에 그럴거야. 다시 말하면 CPython은 현재 메모리와 같은 주소를 반환 할 수 있지만 다른 배포본은 메모리 포인터가 아닌 다른 객체 유형 또는 int를 반환 할 수 있습니다. id()에 의해 반환되는 객체를 얻기위한 함수가 내장되어 있으면 좋을 것입니다. 다른 경우에도 지속성 사용 사례는 상상하기 어렵습니다. 또한 C와 같은 * 변수는 의미가있는 것처럼 보입니다. Python을 좋아합니다. 다른 언어와 마찬가지로 구두점이 부족합니다. – DevPlayer

답변

26

당신은 아마 다른 방법을 구현하는 것을 고려해야 할 것이다. weakref 모듈을 알고 있습니까?

(편집 됨) Python weakref module을 사용하면 참조 카운트에 카운트되지 않은 참조, 사전 참조 및 프록시를 오브젝트에 유지할 수 있습니다. 그것들은 상징적 링크와 같습니다.

+4

때로는 객체에 약한 참조를 생성 할 수 없습니다. TypeError : 'lxml.etree._Element'객체에 약한 참조를 생성 할 수 없습니다. – darkk

32

gc 모듈을 사용하면 현재 Python 가비지 수집기에서 추적 한 모든 객체를 가져올 수 있습니다.

import gc 

def objects_by_id(id_): 
    for obj in gc.get_objects(): 
     if id(obj) == id_: 
      return obj 
    raise Exception("No found") 
+5

이것은 앨리어싱 문제를 가지고 있습니다 : 과거의 임의의 지점에서 얻은 ID가 이제 다른 객체를 참조 할 수 있습니다. – chaos

+6

개체에 대한 참조를 유지했다면 그 일은 일어나지 않습니다. 똑같은, 이것은 일반적으로 나쁜 생각입니다. –

+0

많은 다른 의견 작성자가 동의합니다.하지 마세요. 자신의 사전 개체를 만듭니다. –

34

짧은 답을 할 수 없습니다.

답변 : ID를 개체에 매핑하기위한 사전을 유지하거나 gc.get_objects()의 철저한 검색을 통해 ID를 볼 수는 있지만 두 가지 문제 중 하나가 발생합니다. 사전의 참조가 개체를 유지하고 GC를 방지합니다. , 또는 (WeakValue dict이거나 사용자가 gc.get_objects()을 사용하는 경우) ID가 완전히 다른 오브젝트에 대해 할당 취소되고 재사용 될 수 있습니다.

기본적으로이 작업을 수행하려는 경우 다르게 처리해야 할 수 있습니다. "전문가 전용"으로 표시하지만

+0

개체의'__del__'에 id 참조를 버리려고했지만, 이것이 일이 깨지지 않을 것이라고 생각합니까? –

+6

+1 : 동의 :하지 마십시오. 적절한 키를 사용하여 적절한 사전 개체를 만드는 것만으로도 훨씬 행복해집니다. –

+1

@ cool-RR : 네, 그걸로 안전해야합니다. – chaos

7

완전성을 위해이 모듈을 언급합니다. This code by Bill Bumgarner에는 존재하는 모든 객체 전체에서 반복하지 않고 원하는 것을 수행하는 C 확장이 포함되어 있습니다.

함수에 대한 코드는 매우 간단합니다. 모든 파이썬 객체는 a PyObject struct에 대한 포인터로 C로 표현됩니다. id(x)은이 구조체의 메모리 주소 일 뿐이므로 에 대한 포인터로 x을 처리 한 다음 Py_INCREF을 호출하여 가비지 수집기에 객체에 대한 새 참조를 만들고 있다고 알려줌으로써 Python 객체를 검색 할 수 있습니다.

static PyObject * 
di_di(PyObject *self, PyObject *args) 
{ 
    PyObject *obj; 
    if (!PyArg_ParseTuple(args, "l:di", &obj)) 
     return NULL; 

    Py_INCREF(obj); 
    return obj; 
} 

원본 개체가 더 이상 존재하지 않으면 결과가 정의되지 않습니다. 충돌이 발생할 수 있지만 메모리에있는 이전 객체의 위치를 ​​가져온 새 객체에 대한 참조를 반환 할 수도 있습니다. 개체가 여전히 존재하는 경우

116

,이는 ctypes하여 수행 할 수 있습니다 :

import ctypes 
a = "hello world" 
print ctypes.cast(id(a), ctypes.py_object).value 

출력 : 당신이 개체가 여전히 존재 유무를 알 수없는 경우

hello world 

는, 이것은이다 정의되지 않은 동작과 기묘한 충돌 또는 더 나쁜 것에 대한 레시피이므로 조심하십시오.

a = 0 
id_a = id(a) 
variables = {**locals(), **globals()} 
for var in variables: 
    exec('var_id=id(%s)'%var) 
    if var_id == id_a: 
     exec('the_variable=%s'%var) 
print(the_variable) 
print(id(the_variable)) 

을하지만 더 괜찮은 방법을 구현하는 것이 좋습니다 :

+9

오늘은 어쨌든 CPython에서. : ^) – DSM

+4

이것은 완벽한 답변입니다! –

+8

@HamidFzM 아니,별로. ID가 있으면 객체가 존재하는지 여부도 모릅니다. – glglgl

0

이 할 것입니다.

관련 문제