在Python 3.6中映射函数和迭代

时间:2018-03-20 17:54:02

标签: functional-programming generator python-3.6 iterable

我继承了一段代码,我需要在原来的地方运行,并进行一些细微的修改。我正在尝试map一个字符串列表,使用python 3.6(我不熟悉的语言)将函数应用于该列表的每个元素。

我想使用map而不是列表理解,但现在我怀疑这是可能的。

在以下示例中,我尝试了for循环,yield(或不)和next(...)的组合,但我无法使代码正常工作如预期的那样。

我想看看印刷品:

AAA! xxx 
Found: foo
Found: bar

每次计数器xxx3600(零)。

我理解map函数不执行代码,因此我需要做一些事情来将“函数”“应用”到输入列表的每个元素。

然而,我无法使这件事发挥作用。这篇文档https://docs.python.org/3.6/library/functions.html#maphttps://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

1 个答案:

答案 0 :(得分:0)

我发现对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)来检查生成的iterable的类型和文档,如下所示:

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]: