有人問了一個類似的問題:[Printing all instances of a class]。 儘管我不太關心打印它們,但我更想知道當前有多少實例「活着」。 捕獲此實例的原因更像是設置預定作業,每小時檢查這些「實時」未處理實例並豐富數據。之後,在這個實例中設置一個標誌或者直接刪除這個實例。 Torsten Marek在[question]中的回答:Printing all instances of a class使用weakrefs需要針對此類型的每個類調用基類構造函數,是否可以自動執行此操作?或者我們可以用其他方法獲取所有實例?如何獲取python中某個類的所有實例?
回答
當然,將計一類屬性:
class CountedMixin(object):
count = 0
def __init__(self, *args, **kwargs):
type(self).count += 1
super().__init__(*args, **kwargs)
def __del__(self):
type(self).count -= 1
try:
super().__del__()
except AttributeError:
pass
你可以把這個稍微更神奇與裝飾或元類比一個基類,或者更簡單的,如果它可以是一個有點不太一般(我試圖讓它適合任何合理的多重繼承層次結構中的任何地方,這通常不需要擔心......),但基本上,這就是它的全部。
如果你想擁有這些實例本身(或更好,weakrefs他們),而不僅僅是他們的計數,只是instances=set()
取代count=0
,然後做instances.add(self)
代替count += 1
等。(此外,雖然,你可能要一個weakref到self
,而不是self
)
您可以跟蹤它自己(見其他答案),或要求垃圾收集器:
import gc
class Foo(object):
pass
foo1, foo2 = Foo(), Foo()
foocount = sum(1 for o in gc.get_referrers(Foo) if o.__class__ is Foo)
這可能是近親如果你有很多對象,那麼速度就會變慢,但它通常不會太壞,而且它的好處是你可以很容易地與別人的代碼一起使用。
如果你想讓它趕上subclasess爲好,改變if
子句中的發電機表達:... if isinstance(o, Foo))
注意:用於o.__class__
而不是type(o)
所以它適用於老式類。
+1]。這對於每小時一次檢查來說很可能沒有問題,並且沒有使用'__del__'造成的副作用 –
如果你只希望這對CPython的工作,你的「活」的定義可以稍微鬆懈,還有另一種方式來做到這一點,可能對調試/內省目的有用:
>>> import gc
>>> class Foo(object): pass
>>> spam, eggs = Foo(), Foo()
>>> foos = [obj for obj in gc.get_objects() if isinstance(obj, Foo)]
>>> foos
[<__main__.Foo at 0x1153f0190>, <__main__.Foo at 0x1153f0210>]
>>> del spam
>>> foos = [obj for obj in gc.get_objects() if isinstance(obj, Foo)]
>>> foos
[<__main__.Foo at 0x1153f0190>, <__main__.Foo at 0x1153f0210>]
>>> del foos
>>> foos = [obj for obj in gc.get_objects() if isinstance(obj, Foo)]
>>> foos
[<__main__.Foo at 0x1153f0190>]
請注意,刪除spam
實際上並沒有使其無法生效,因爲我們仍然參照foos
中的同一對象。並且重新分配foos
並沒有幫助,因爲顯然在發佈舊版本之前發生了對get_objects
的調用。但最終,一旦我們停止提及它,它就會消失。
解決此問題的唯一方法是使用weakrefs。
當然,在一個大系統中,這個速度可能會非常慢,有或沒有弱點。
我不能kindall的答案發表評論,因此,我寫我的批評是對的答案:
與gc.get_referrers(<ClassName>)
的解決方案並不在Python 3 gc.get_referrers(<ClassName>)
不返回任何類實例的方法與繼承的類工作這是繼承自<ClassName>
。
相反,您需要使用gc.get_objects()
,因爲它返回完整的對象列表,所以速度要慢很多。但是在單元測試的情況下,你只是想確保你的對象在測試後被刪除(沒有循環引用),它應該足夠快。
也請不要忘記在檢查實例的數量之前先調用gc.collect()
,以確保所有未引用的實例都被真正刪除。
我還看到一個弱引用的問題,這也是以這種方式計算的。弱引用的問題是,被引用的對象可能不再存在,因此isinstance(Instance, Class)
可能會失敗,並顯示關於不存在的弱引用的錯誤。
下面是一個簡單的代碼示例:
import gc
def getInstances(Class):
gc.collect()
Number = 0
InstanceList = gc.get_objects()
for Instance in InstanceList:
if 'weakproxy' not in str(type(Instance)): # avoid weak references
if isinstance(Instance, Class):
Number += 1
return Number
- 1. 如何獲取或殺死某些類的所有實例?
- 2. 獲取某個類的實例
- 3. javascript:如何覆蓋某個類的所有實例的方法?
- 4. SPARQL:獲取某個類的子類的所有實體
- 5. 在PHP中獲取一個類的所有實例
- 6. 如何在一個對象的實例中獲取某個類型的所有值/成員
- 7. 如何獲取某個城市中某個類型的所有Google地點?
- 8. 如何獲取當前模塊中的一個類的所有實例
- 9. 如何獲取對象是實例的所有接口和類?
- 10. 如何獲取類/實例的所有屬性?
- 11. Selenium/Python:如何獲取與另一個類相同級別的類中的所有按鈕實例?
- 12. Python - 如何從屬性類中獲取類實例引用?
- 13. 如何獲得Dart中某個類的所有子類?
- 14. Actionscript 3.0獲取一個類的所有實例?
- 15. 如何從JSON數組中獲取具有某個名稱的所有實體
- 16. 獲取某個類的所有錨的某些屬性
- 17. 如何獲取有關Oracle中某個表的所有信息?
- 18. 獲取目標c中的類的所有實例?
- 19. 如何在Ruby中獲取類實例?
- 20. Python:獲取實例化類的名字?
- 21. 如何獲取任何類的實例?
- 22. 獲取在類中聲明的所有實例變量
- 23. 在jquery或js中獲取類的所有實例
- 24. 獲取python中的所有超類3
- 25. 獲取Python包中的所有類名
- 26. C#控制反轉 - 獲取實例化基類的所有類
- 27. 如何從導入的模型中獲取所有類的實例?
- 28. Google-guice:將同一類的所有實例綁定到某個實例
- 29. 如何使用python獲取所有沒有特定標籤的mysql實例?
- 30. 如何獲取jQuery中沒有獲得某個類的項目?
也許值得一提:與任何依賴於'__del__'方法,這可能會導致非直觀的行爲。例如:'CountedMixin()'使'CountedMixin.count'增加一段時間,即使新對象不可訪問。 –
'__del__'也可以防止循環垃圾回收器在這些對象上工作 –
@gnibbler:是的,如果你想創建對象的循環並且掛鉤它們的銷燬,你需要添加你自己的循環斷路器到'gc.callbacks' 。 – abarnert