Как распечатать прогресс понимания списка в Python? - PullRequest
0 голосов
/ 08 июня 2018

В моем методе я должен вернуть список в списке.Я хотел бы иметь понимание списка, потому что производительность, так как создание списка занимает около 5 минут.

[[token.text for token in document] for document in doc_collection]

Есть ли возможность распечатать прогресс, в каком документе процесс создания в настоящее времяявляются?Примерно так:

[[token.text for token in document] 
  and print(progress) for progress, document in enumerate(doc_collection)]

Спасибо за помощь!

Ответы [ 4 ]

0 голосов
/ 19 августа 2019

Мне нужно сделать ответ @ ted (imo) более читабельным и добавить некоторые объяснения.

Приведенное в порядок решение:

# Function to print the index, if the index is evenly divisable by 1000:
def report(index):
    if index % 1000 == 0:
        print(index)

# The function the user wants to apply on the list elements
def process(x, index, report):
     report(index) # Call of the reporting function
     return 'something ' + x # ! Just an example, replace with your desired application

# !Just an example, replace with your list to iterate over
mylist = ['number ' + str(k) for k in range(5000)]

# Running a list comprehension
[process(x, index, report) for index, x in enumerate(mylist)]

Объяснение: из enumerate(mylist): с помощью функции enumerate можно иметь индексы в дополнение к элементам итерируемого объекта (ср. этот вопрос и его ответы ).Например,

[(index, x) for index, x in enumerate(["a", "b", "c"])] #returns
[(0, 'a'), (1, 'b'), (2, 'c')]

Примечание: index и x не являются зарезервированными именами, только имена, которые я считаю удобными - [(foo, bar) for foo, bar in enumerate(["a", "b", "c"])] дает тот же результат.

0 голосов
/ 08 июня 2018

1: использование побочной функции

def report(index):
    if index % 1000 == 0:
        print(index)

def process(token, index, report=None):
    if report:
        report(index) 
    return token['text']

l1 = [{'text': k} for k in range(5000)]

l2 = [process(token, i, report) for i, token in enumerate(l1)]

2: использование and и or операторов

def process(token):
    return token['text']

l1 = [{'text': k} for k in range(5000)]
l2 = [(i % 1000 == 0 and print(i)) or process(token) for i, token in enumerate(l1)]

3: использование обоих

def process(token):
    return token['text']

def report(i):
    i % 1000 == 0 and print(i)

l1 = [{'text': k} for k in range(5000)]
l2 = [report(i) or process(token) for i, token in enumerate(l1)]

Все 3 метода печати:

0
1000
2000
3000
4000

Как работает 2

  • i % 1000 == 0 and print(i): and проверяет только второйоператор, если первый является True, поэтому печатается только тогда, когда i % 1000 == 0
  • or process(token): or всегда проверяет оба оператора, но возвращает первый, который имеет значение True.
    • Если i % 1000 != 0, то первым оператором будет False и process(token) будет добавлен в список.
    • Иначе, тогда первый оператор будет None (потому что print возвращает None) и аналогично, оператор or добавляет process(token) в список

Как работает 3

Аналогично 2, потому что report(i) ничего не делает return, оно превращается в None и or добавляет process(token)к списку

0 голосов
/ 08 июня 2018
def show_progress(it, milestones=1):
    for i, x in enumerate(it):
        yield x
        processed = i + 1
        if processed % milestones == 0:
            print('Processed %s elements' % processed)

Просто примените эту функцию ко всему, что вы повторяете.Не имеет значения, используете ли вы циклическое или списочное понимание, и его легко использовать где угодно, практически без изменений кода.Например:

doc_collection = [[1, 2],
                  [3, 4],
                  [5, 6]]

result = [[str(token) for token in document]
          for document in show_progress(doc_collection)]

print(result)  # [['1', '2'], ['3', '4'], ['5', '6']]

Если вы хотите показать прогресс только для каждых 100 документов, напишите:

show_progress(doc_collection, 100) 
0 голосов
/ 08 июня 2018
doc_collection = [[1, 2],
                  [3, 4],
                  [5, 6]]

result = [print(progress) or
          [str(token) for token in document]
          for progress, document in enumerate(doc_collection)]

print(result)  # [['1', '2'], ['3', '4'], ['5', '6']]

Я не считаю этот хороший или читабельный код, но идея забавная.

Это работает, потому что print всегда возвращает None, поэтому print(progress) or x всегда будет x(по определению or).

...