2009-09-08 283 views
83

比方說,我有一個Python對象的id,我通過id(thing)進行檢索。我怎麼找到thing再次由我給的身份證號碼?通過id()獲取對象?

+0

我很好奇:你爲什麼想這樣做?你的目標是什麼? – 2009-09-09 12:35:58

+1

@Craig McQueen:http:// stackoverflow。com/questions/1400295/python-class-for-pickle-and-copy-persistent-object – 2009-09-10 18:06:57

+0

我無法重新找到這個源,但我認爲id()返回的是特定分發需要的東西它是。現在,重新生成的CPython現在可能會返回一個類似於內存的地址,但其他發行版可能會返回不同的對象類型或不是內存指針的整數。如果有一個內置函數通過id()返回的內容來獲取對象,那將會很好。儘管其他持久性用例很難想象。同樣,儘管*變量,像C似乎是有道理的;我喜歡Python,因爲它像大多數其他語言一樣缺乏標點欺騙。 – DevPlayer 2015-06-24 02:34:36

回答

26

你可能要考慮實現它的另一種方式。你意識到weakref模塊嗎?

(編輯)Python weakref module可讓您保留對象的引用,字典引用和代理,而不必在引用計數器中計算這些引用。它們就像符號鏈接。

+4

有時您不能創建對該對象的弱引用,例如:TypeError:無法創建對'lxml.etree._Element'對象的弱引用 – darkk 2011-06-23 09:17:03

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 2009-09-08 22:37:59

+6

只要你保留了對象的引用,就不會發生。同樣,這通常是一個壞主意。 – 2009-09-08 23:16:53

+0

我同意許多其他評論者:不要這樣做。製作你自己的對象字典。 – 2009-09-09 11:26:23

34

簡短的回答,你不能。

很長的答案,你可以保留一個字典,將ID映射到對象,或通過詳盡搜索gc.get_objects()來查找ID,但這會產生以下兩個問題之一:或者字典的引用會使對象保持活動狀態並阻止GC ,或者(如果它是一個WeakValue字典或者您使用gc.get_objects()),該ID可能會被重新分配並重新用於完全不同的對象。

基本上,如果你想要做到這一點,你可能需要做一些不同的事情。

+0

我一直打算拋棄對象的'__del__'中的id引用,你認爲這會確保事情不會中斷嗎? – 2009-09-08 22:44:58

+6

+1:同意:不要這樣做。只需用適當的鍵創建一個適當的對象字典 - 你會更快樂。 – 2009-09-08 23:51:03

+1

@ cool-RR:是的,你應該安全。 – chaos 2009-09-09 12:57:13

7

只是提到這個模塊的完整性。 This code by Bill Bumgarner包含一個C擴展,可以完成您想要的任何操作,而無需循環遍歷每個對象。

該函數的代碼非常簡單。每個Python對象都用C指向a PyObject struct。由於id(x)只是此結構的內存地址,我們可以通過將x作爲指向PyObject的指針來檢索Python對象,然後調用Py_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; 
} 

如果原始對象不再存在,則結果是未定義的。它可能會崩潰,但它也可能返回一個對舊內存中的舊對象的引用。

116

如果對象仍然存在,這可以通過ctypes完成:

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

輸出:

hello world 

如果你不知道該對象是否仍然存在,這是一個配方不明確的行爲和怪異的崩潰或更糟,所以要小心。

+9

無論如何在今天的CPython中。 :^) – DSM 2013-03-29 14:24:48

+4

這是一個完美的答案! – 2013-11-11 21:44:00

+8

@HamidFzM不,不是真的。如果我有一個ID,我可能甚至不知道該對象是否仍然存在。 – glglgl 2014-07-21 08:13:01

0

這樣做:

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

但我建議實施一個更體面的方式。

相關問題