разделить генератор / повторяемый каждые n элементов в Python (splitEvery)

Когда метод 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 () вызывается путем его переопределения. Он не выполнен. Может ли кто-нибудь сказать мне причину, по которой он не выполняется?

Трудно сказать, но есть несколько возможностей:

  • Объект не
  • Объект не собирает мусор, потому что GC не запускается до завершения вашего теста.
  • Объект найден GC и помещен в завершение очереди GC, но до завершения теста завершение не завершено.
29
задан James Brooks 16 December 2009 в 15:21
поделиться

8 ответов

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, []))
[]
46
ответ дан Roberto Bonvallet 16 December 2009 в 15:21
поделиться

Почему бы не сделать это так? Выглядит почти как ваша splitEvery_2 функция.

def splitEveryN(n, it):
    return [it[i:i+n] for i in range(0, len(it), n)]

На самом деле это только убирает ненужный интервал шага из среза в вашем решении. :)

1
ответ дан Johannes Charra 16 December 2009 в 15:21
поделиться

Однострочное, встроенное решение для этого (поддерживает 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))
3
ответ дан Andrey Cizov 16 December 2009 в 15:21
поделиться

Вот как вы работаете со списком и итератором:

def isList(L): # Implement it somehow - returns True or false
...
return (list, lambda x:x)[int(islist(L))](result)
0
ответ дан Hamish Grubijan 16 December 2009 в 15:21
поделиться

more_itertools имеет функцию chunked :

import more_itertools as mit


list(mit.chunked(range(9), 5))
# [[0, 1, 2, 3, 4], [5, 6, 7, 8]]
6
ответ дан Elliot Cameron 16 December 2009 в 15:21
поделиться

Вот быстрая однострочная версия. Как и у Хаскелла, он ленивый.

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 за улучшения.)

19
ответ дан Elliot Cameron 16 December 2009 в 15:21
поделиться

Я думаю, что эти вопросы почти равны

. Если немного подрезать последние, я думаю, что хорошим решением для случая генератора было бы:

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)

Я думаю, вы могли бы немного отполировать: -)

2
ответ дан Community 16 December 2009 в 15:21
поделиться

это сделает трюк

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 () для результата.

-1
ответ дан Mr. Me 16 December 2009 в 15:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: