Programing

id ()로 객체를 가져 옵니까?

crosscheck 2020. 7. 30. 09:53
반응형

id ()로 객체를 가져 옵니까?


파이썬 객체의 id를 가지고 있다고 가정 해 봅시다 id(thing). thing받은 ID 번호로 어떻게 다시 찾을 수 있습니까?


아마도 다른 방법으로 구현하는 것이 좋습니다. weakref 모듈에 대해 알고 있습니까?

(편집) Python weakref 모듈을 사용하면 참조 카운터에서 참조를 계산하지 않고도 객체에 대한 참조, 사전 참조 및 프록시를 유지할 수 있습니다. 그것들은 상징적 링크와 같습니다.


객체가 여전히 있으면 다음과 같이 수행 할 수 있습니다 ctypes.

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

산출:

hello world

객체가 여전히 존재하는지 모르는 경우, 이것은 정의되지 않은 동작과 이상한 충돌 또는 더 나쁜 요리법입니다.


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")

짧은 대답, 당신은 할 수 없습니다.

긴 대답으로 ID를 객체에 매핑하는 dict를 유지하거나 철저한 검색을 통해 ID를 조회 gc.get_objects()할 수 있지만 두 가지 문제 중 하나가 발생합니다. dict의 참조는 객체를 활성 상태로 유지하고 GC를 방지합니다. WeakValue dict 또는)를 사용 gc.get_objects()하면 완전히 다른 객체에 대해 ID를 할당 해제하고 재사용 할 수 있습니다.

기본적으로이 작업을 수행하려는 경우 다르게 수행해야합니다.


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

함수 코드는 매우 간단합니다. 모든 파이썬 객체에 대한 포인터로 C로 표시됩니다 구조체 . 이 구조체의 메모리 주소 일 뿐이 므로 ,에 대한 포인터로 취급 한 다음 가비지 수집기에게 개체에 대한 새로운 참조를 만들도록 호출 하여 Python 개체를 검색 할 수 있습니다 .PyObjectid(x)xPyObjectPy_INCREF

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

    Py_INCREF(obj);
    return obj;
}

원래 객체가 더 이상 존재하지 않으면 결과는 정의되지 않습니다. 충돌 할 수는 있지만 메모리에서 이전 객체의 위치를 ​​차지한 새 객체에 대한 참조를 반환 할 수도 있습니다.


"전문가 전용"으로 표시되어 있지만 eGenix mxTools 라이브러리는 이러한 기능을 제공합니다. mx.Tools.makeref(id)


이것은 할 것이다 :

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))

그러나 더 적절한 방법으로 구현하는 것이 좋습니다.

참고 URL : https://stackoverflow.com/questions/1396668/get-object-by-id

반응형