Функция карты и итерации в python 3.6

Я унаследовал фрагмент кода, который мне нужно запустить где-то еще, кроме исходного места, с небольшими изменениями. Я пытаюсь map составить список строк для чего-то, что применяет функцию к каждому элементу этого списка, используя python 3.6 (язык, с которым я не знаком).

Я хотел бы использовать map не понимание списка, но теперь я сомневаюсь, что это возможно.

В следующем примере я попробовал комбинацию циклов for, yield (или нет) и next(...) или нет, но не могу заставить код работать должным образом.

Я хотел бы увидеть печать:

AAA! xxx 
Found: foo
Found: bar

каждый раз, когда счетчик xxx по модулю 360 равен 0 (нулю).

Я понимаю, что функция map не выполняет код, поэтому мне нужно что-то сделать, чтобы «применить» эту функцию к каждому элементу входного списка.

Однако я не могу заставить эту вещь работать. Эта документация https://docs.python.org/3.6/library/functions.html#map и https://docs.python.org/3.6/howto/functional.html#iterators не очень помогает, я прошел через это и думаю, что по крайней мере один из закомментированных фрагментов ниже (# <python code>) должен был сработать. Я не опытный разработчик Python, и я думаю, что мне не хватает некоторых ошибок в синтаксисе/условиях Python 3.6 в отношении итераторов/генераторов.

issue_counter = 0

def foo_func(serious_stuff):
    # this is actually a call to a module to send an email with the "serious_stuff"
    print("Found: {}".format(serious_stuff))

def report_issue():
    global issue_counter
    # this actually executes once per minute (removed the logic to run this fast)
    while True:
        issue_counter += 1
        # every 6 hours (i.e. 360 minutes) I would like to send emails
        if issue_counter % 360 == 0:
            print("AAA! {}".format(issue_counter))
            # for stuff in map(foo_func, ["foo", "bar"]):
                # yield stuff
                # stuff()
                # print(stuff)
            iterable_stuff = map(foo_func, ["foo", "bar"])
            for stuff in next(iterable_stuff):
                # yield stuff
                print(stuff)

report_issue()

Я получаю много разных ошибок/неожиданного поведения этого цикла for при запуске скрипта:

  • ничего не печатает, когда я звоню print(...)
  • TypeError: 'NoneType' object is not callable
  • AttributeError: 'map' object has no attribute 'next'
  • TypeError: 'NoneType' object is not iterable
  • Печать того, что я ожидаю, с чередованием None, например:
AAA! 3047040
Found: foo
None
Found: bar
None

person TPPZ    schedule 20.03.2018    source источник


Ответы (1)


Я обнаружил, что вызов next(iterable_thingy) на самом деле вызывает сопоставленную функцию.

Зная длину входного списка при отображении его для создания итерируемого объекта, мы знаем, сколько раз нам нужно вызвать next(iterable_thingy), поэтому функция report_issue (в моем предыдущем примере) работает, как и ожидалось, если определена следующим образом:

def report_issue():
    global issue_counter
    original_data = ["foo", "bar"]
    # this executes once per minute
    while True:
        issue_counter += 1
        # every 6 hours I would like to send emails
        if issue_counter % 360 == 0:
            print("AAA! {}".format(issue_counter))

            iterable_stuff = map(foo_func, original_data)
            for idx in range(len(original_data)):
                next(iterable_stuff)

Чтобы устранить неполадки с этим итерируемым материалом, я счел полезным запустить ipython (интерактивный REPL), чтобы проверить тип и документацию сгенерированного итерируемого объекта, например:

In [2]: def foo_func(serious_stuff):
    ...:     # this is actually a call to a module to send an email with the "serious_stuff"
    ...:     print("Found: {}".format(serious_stuff))    ...: 

In [3]: iterable_stuff = map(foo_func, ["foo", "bar"])

In [4]: iterable_stuff? 
Type:        map 
String form: <map object at 0x7fcdbe8647b8> 
Docstring:   
map(func, *iterables) --> map object

Make an iterator that computes the function using arguments from 
each of the iterables.  Stops when the shortest iterable is exhausted.

In [5]: next(iterable_stuff) Found: foo

In [6]: bar_item = next(iterable_stuff) Found: bar

In [7]: bar_item? 
Type:        NoneType 
String form: None 
Docstring:   <no docstring>

In [8]:
person TPPZ    schedule 21.03.2018