2016-07-21 2 views
1

Я пишу функцию, которая принимает огромный аргумент и работает в течение длительного времени. Для этого аргумент нужен только наполовину. Есть ли способ для функции удалить значение, на которое указывает аргумент, если больше нет ссылок на него?Как удалить аргумент функции раньше?

Я был в состоянии получить его удален, как только функция возвращает, например:

def f(m): 
    print 'S1' 
    m = None 
    #__import__('gc').collect() # Uncommenting this doesn't help. 
    print 'S2' 
class M(object): 
    def __del__(self): 
    print '__del__' 
f(M()) 

Это печатает:

S1 
S2 
__del__ 

мне нужно:

S1 
__del__ 
S2 

Я был также пытается def f(*args): и def f(**kwargs), но это не помогло, я до сих пор получаю __del__ последний.

Обратите внимание, что мой код полагается на то, что Python имеет подсчет ссылок, а __del__ вызывается, как только счетчик ссылок объекта падает до нуля. Я хочу, чтобы счетчик ссылок аргумента функции упал до нуля в середине функции. Это возможно?

Пожалуйста, обратите внимание, что я знаю, что обходной путь: передавая список аргументов:

def f(ms): 
    print 'S1' 
    del ms[:] 
    print 'S2' 
class M(object): 
    def __del__(self): 
    print '__del__' 
f([M()]) 

Печатается:

S1 
__del__ 
S2 

Есть ли способ, чтобы получить раннее удаление без изменения API (например, ввод списков в аргументы)?

Если трудно получить портативное решение, которое работает во многих реализациях Python, мне нужно что-то, что работает в самом последнем CPython 2.7. Его не нужно документировать.

+2

Почему вы хотите это сделать? Вообще-то я думаю, что python не будет мусора собирать что-то, как только он ссылается на количество обращений 0, но только некоторое (не определенное) время после. Вы должны иметь возможность принудительно собирать мусор. – syntonym

+1

Аргумент передается из области вызова. В конечном итоге объект все еще упоминается там.Однако при низком уровне вы снижаете количество ссылок в вашей функции, пока ваша функция не закончит объект, вероятно, не будет собран мусор, потому что ссылки на область действия родителя еще не очищены. - Это в значительной степени просто предположение, но я не знаю, как поведение будет отличаться между 'foo (m)' и 'foo (M())'; логика диктует, что он не должен * отличаться, но это зависит от реализации. – deceze

+0

Я * хочу * сказать, что даже если вы отвязаете аргумент, он все еще существует вне области действия. –

ответ

0

Похоже, что раннее удаление в CPython 2.7 невозможно без изменения API функции f.

1

От the documentation:

CPython деталь реализации: CPython в настоящее время использует схему подсчета ссылок с (необязательно) с задержкой обнаружения циклический связанным мусор, который собирает большинство объектов, как только они становятся недостижимыми, но не является гарантированно собирать мусор, содержащий круглые ссылки. Информацию об управлении сбором циклического мусора см. В документации модуля gc. Другие реализации действуют по-разному, и CPython может измениться. Не зависеть от непосредственной доработки объектов, когда они становятся недоступными (например: всегда закрывать файлы).

Short модифицирующих переводчику себя, вы не может достичь того, чего вы хотите. __del__ будет вызываться, когда интерпретатор решает это сделать.

+0

Или вы сами это называете. Даже тогда память не может быть восстановлена ​​немедленно, если вообще когда-либо. – martineau

+0

Спасибо за цитату. Это доказывает, что в CPython не существует документального и перспективного способа сделать это. Я уточнил вопрос: я бы принял даже недокументированное решение, которое работает в CPython 2.7. – pts

+0

@martineau: Вызов 'm .__ del __()' вручную мне не помогает. Мне не нужно вызывать '__del__', я просто использую' __del__' в качестве индикатора, который интерпретатор Python хочет удалить. Мне очень важно, чтобы объект был удален раньше. – pts

Смежные вопросы