TL; DR
Вам нужен del
потому vector
не класс питона.
Более длинный ответ
Есть много факторов, которые делают невозможным для питоны сборщика мусора, чтобы собрать этот объект:
vector
экземпляры не имеют атрибут справочно-счет, потому что их класс/struct не включает PyObject_HEAD
. Это класс C (C++), так зачем?
объекты Python использовать PyObject_GC_New
, чтобы сделать их экземпляр, известный коллектор мусора и PyObject_GC_Del
(или PyObject_GC_UnTrack
) для удаления. Однако vector
использует new
для создания (на куче), поэтому сборщик мусора не участвует вообще и, следовательно, вам нужен явный del
(я думаю, delete
также должен работать, но я не проверял) для удаления.
Это можно увидеть в исходном коде, а также (я использую ipythons %%cython
поэтому примеры воспроизводимые):
%%cython --cplus
from libcpp.vector cimport vector
def simple_test(double x):
v = new vector[double]()
try:
v.push_back(1.0)
v.push_back(x)
from math import pi
v.push_back(pi)
return v.size()
finally:
del v
дает следующее (экстремально) укороченный код в файле .cpp
(обычно это файл находится в папке .ipython/cython
в вашем домашнем каталоге):
/* "_cython_magic_9df9dbf5f4981f282eb46337245f3bb9.pyx":9
* 3
* """
* v = new vector[double]() # <<<<<<<<<<<<<<
* try:
* v.push_back(1.0)
*/
try {
__pyx_t_1 = new std::vector<double>();
} catch(...) {
[...]
}
__pyx_v_v = __pyx_t_1;
/* "_cython_magic_9df9dbf5f4981f282eb46337245f3bb9.pyx":17
* return v.size()
* finally:
* del v # <<<<<<<<<<<<<<
*/
[...]
{
delete __pyx_v_v;
}
Так что без del v
там Wo uld be no delete
, и у вас (вероятно) есть утечка памяти в вашем коде.
Практический тест
%%cython --cplus
from libcpp.vector cimport vector
def simple_test(double x):
v = new vector[double]()
for _ in range(20000000):
v.push_back(x)
return v.size()
# NO "del"!!!
import psutil
for _ in range(10):
simple_test(10)
print(psutil.virtual_memory().percent)
который печатает:
47.5
49.4
51.2
53.1
55.1
57.0
58.9
60.8
62.8
65.0
66.9
68.9
70.6
72.5
74.5
76.4
78.4
80.3
82.2
83.6
Так, по крайней мере на моем компьютере это приводит к постоянно увеличивается использование памяти, в то время как один с del
не:
%%cython --cplus
from libcpp.vector cimport vector
def simple_test(double x):
v = new vector[double]()
try:
for _ in range(20000000):
v.push_back(x)
return v.size()
finally:
del v # this one has a del statement!!!
import psutil
for _ in range(20):
simple_test(10)
print(psutil.virtual_memory().percent)
Результат:
47.4
47.4
47.4
47.4
47.4
47.4
47.4
47.4
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.3
Сборщик мусора автоматически очистит его. – Barmar
@ Бармар Я так не думаю. Помимо теоретических соображений (потому что это объект C, а не объект Python, как бы знать pythons gc, когда и как его собирать), просто запуск этого кода вызывает утечку памяти на моем компьютере. – MSeifert