Отслеживание размещения объектов в python
Можно ли переопределить какой-либо метод, который позволит мне использовать операторы печати/pdb/и т.д., чтобы отслеживать каждый раз, когда выделяется экземпляр моего класса? Пока вы клонируете некоторые объекты, я, похоже, получаю то, что никогда не вызывало на них __setstate__
или __init__
. Я попытался переопределить __new__
и распечатать идентификатор каждого объекта, который я делаю в __new__
, но я все еще сталкиваюсь с объектами с идентификаторами, которые никогда не были напечатаны.
Изменить: вот мой код, который я использую для изменения (инструментария) __new__
моего класса и всех его суперклассов, кроме самого object
:
class Allocator:
def __init__(self, my_class):
self.my_class = my_class
self.old_new = my_class.__new__
def new(self, * args, ** kargs):
rval = self.old_new(*args, ** kargs)
#rval = super(self.my_class,cls).__new__(cls)
print 'Made '+str(self.my_class)+' with id '+str(id(rval))
return rval
def replace_allocator(cls):
if cls == object:
return
setattr(cls,'__new__',Allocator(cls).new)
print cls.__base__
try:
for parent in cls.__base__:
replace_allocator(parent)
except:
replace_allocator(cls.__base__)
Я вызываю replace_allocator в родительский класс моих классов, как только он импортируется в основном script. У моего класса есть пользовательский __new__
, который также выводит идентификатор.
Ответы
Ответ 1
(Это скорее комментарий, чем ответ.)
Цитирование Guido Унификация типов и классов в Python 2.2:
Бывают ситуации, когда новый экземпляр создается без вызова __init__
(например, когда экземпляр загружается из рассола). Невозможно создать новый экземпляр без вызова __new__
(хотя в некоторых случаях вы можете уйти с вызовом базового класса __new__
).
Если вы используете классы нового стиля (потомки object
), всегда следует вызывать __new__()
. Я не думаю, что неясные случаи, "вы можете уйти с вызовом базового класса __new__
", произойдут случайно, хотя я не знаю, каковы эти случаи на самом деле.
И просто добавьте пример:
In [1]: class A(object):
...: def __new__(cls):
...: print "A"
...: return object.__new__(cls)
...:
In [2]: A()
A
Out[2]: <__main__.A object at 0xa3a95cc>
In [4]: object.__new__(A)
Out[4]: <__main__.A object at 0xa3a974c>
Ответ 2
Используете ли вы классы нового стиля? Чтобы Pickle вызывал __setstate__
, метод __getstate__
также должен быть определен в классе возвращающем значение, отличное от False.
Ответ 3
Не уверен, что это может вам помочь, но сборщик мусора Python имеет интроспективные возможности, на которые стоит обратить внимание.