Когда метод
blockquote>finalize()
вызывается в Java?Метод finalize вызывается после того, как GC обнаружит, что объект больше недоступен, и до того, как он на самом деле восстанавливает память, используемую объектом.
- Если объект никогда не становится недоступным,
finalize()
никогда не будет вызываться на нем.- Если GC не запускается,
finalize()
никогда не может быть вызвана. (Обычно GC работает только тогда, когда JVM решает, что, вероятно, будет достаточно мусора, чтобы сделать его стоящим.)- Может потребоваться более одного цикла GC до того, как GC определит, что конкретный объект недоступен. (Java-GC, как правило, являются «генераторными» коллекторами ...)
- Как только GC обнаруживает, что объект недоступен и финализирован, он помещается в очередь финализации.
(Фактическая спецификация JVM позволяет JVM в never запускать финализаторы ... при условии, что что он не восстанавливает пространство, используемое объектами. JVM, который был реализован таким образом, будет искалечен / бесполезен, но это поведение «разрешено».)
В результате получается, что это неразумно полагаться на завершение, чтобы делать то, что нужно делать в определенные сроки. Это «лучшая практика», чтобы не использовать их вообще. Должен быть лучший (то есть более надежный) способ делать то, что вы пытаетесь сделать в методе
finalize()
.Единственное законное использование для финализации - очистка ресурсов, связанных с объектами, которые были потеряны кодом приложения. Даже тогда вы должны попытаться написать код приложения, чтобы он не потерял объекты в первую очередь. (Например, используйте Java 7+ try-with-resources , чтобы гарантировать, что
close()
всегда вызывается ...)
Я создал тест класс, который записывает в файл, когда метод finalize () вызывается путем его переопределения. Он не выполнен. Может ли кто-нибудь сказать мне причину, по которой он не выполняется?
blockquote>Трудно сказать, но есть несколько возможностей:
- Объект не
- Объект не собирает мусор, потому что GC не запускается до завершения вашего теста.
- Объект найден GC и помещен в завершение очереди GC, но до завершения теста завершение не завершено.
from itertools import islice
def split_every(n, iterable):
i = iter(iterable)
piece = list(islice(i, n))
while piece:
yield piece
piece = list(islice(i, n))
Некоторые тесты:
>>> list(split_every(5, range(9)))
[[0, 1, 2, 3, 4], [5, 6, 7, 8]]
>>> list(split_every(3, (x**2 for x in range(20))))
[[0, 1, 4], [9, 16, 25], [36, 49, 64], [81, 100, 121], [144, 169, 196], [225, 256, 289], [324, 361]]
>>> [''.join(s) for s in split_every(6, 'Hello world')]
['Hello ', 'world']
>>> list(split_every(100, []))
[]
Почему бы не сделать это так? Выглядит почти как ваша splitEvery_2
функция.
def splitEveryN(n, it):
return [it[i:i+n] for i in range(0, len(it), n)]
На самом деле это только убирает ненужный интервал шага из среза в вашем решении. :)
Однострочное, встроенное решение для этого (поддерживает v2 / v3, итераторы, использует стандартную библиотеку и понимание одного генератора):
import itertools
def split_groups(iter_in, group_size):
return ((x for _, x in item) for _, item in itertools.groupby(enumerate(iter_in), key=lambda x: x[0] // group_size))
Вот как вы работаете со списком и итератором:
def isList(L): # Implement it somehow - returns True or false
...
return (list, lambda x:x)[int(islist(L))](result)
more_itertools
имеет функцию chunked
:
import more_itertools as mit
list(mit.chunked(range(9), 5))
# [[0, 1, 2, 3, 4], [5, 6, 7, 8]]
Вот быстрая однострочная версия. Как и у Хаскелла, он ленивый.
from itertools import islice, takewhile, repeat
split_every = (lambda n, it:
takewhile(bool, (list(islice(it, n)) for _ in repeat(None))))
Для этого необходимо использовать iter
до вызова split_every
.
Пример:
list(split_every(5, iter(xrange(9))))
[[0, 1, 2, 3, 4], [5, 6, 7, 8]]
Хотя это и не одна строка, в приведенной ниже версии не требуется, чтобы вы называли iter
, что может быть распространенной ошибкой.
from itertools import islice, takewhile, repeat
def split_every(n, iterable):
"""
Slice an iterable into chunks of n elements
:type n: int
:type iterable: Iterable
:rtype: Iterator
"""
iterator = iter(iterable)
return takewhile(bool, (list(islice(iterator, n)) for _ in repeat(None)))
(Спасибо @ eli-korvigo за улучшения.)
Я думаю, что эти вопросы почти равны
. Если немного подрезать последние, я думаю, что хорошим решением для случая генератора было бы:
from itertools import *
def iter_grouper(n, iterable):
it = iter(iterable)
item = itertools.islice(it, n)
while item:
yield item
item = itertools.islice(it, n)
для объекта, который поддерживает слайсы (списки, строки, кортежи), мы можем сделать:
def slice_grouper(n, sequence):
return [sequence[i:i+n] for i in range(0, len(sequence), n)]
теперь это просто вопрос выбора правильного метода:
def grouper(n, iter_or_seq):
if hasattr(iter_or_seq, "__getslice__"):
return slice_grouper(n, iter_or_seq)
elif hasattr(iter_or_seq, "__iter__"):
return iter_grouper(n, iter_or_seq)
Я думаю, вы могли бы немного отполировать: -)
это сделает трюк
from itertools import izip_longest
izip_longest(it[::2], it[1::2])
, где * it * является итеративным
Пример:
izip_longest('abcdef'[::2], 'abcdef'[1::2]) -> ('a', 'b'), ('c', 'd'), ('e', 'f')
Давайте разберем это
'abcdef'[::2] -> 'ace'
'abcdef'[1::2] -> 'bdf'
Как вы можете видеть, последний номер в срезе указывает интервал, который будет использоваться для сбора предметов. Вы можете прочитать больше об использовании расширенных срезов здесь .
Функция zip берет первый элемент из первой итерируемой и объединяет его с первым элементом со второй итерируемой. Затем функция zip делает то же самое для второго и третьего элементов, пока у одного из итераций не заканчиваются значения.
Результатом является итератор. Если вы хотите список, используйте функцию list () для результата.