【问题标题】:Map function and iterables in python 3.6python 3.6中的映射函数和迭代
【发布时间】:2018-08-29 16:11:55
【问题描述】:

我继承了一段代码,我需要在原始位置以外的其他地方运行该代码,并进行了一些细微的更改。我正在尝试 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

【问题讨论】:

    标签: functional-programming generator python-3.6 iterable


    【解决方案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]:
    

    【讨论】:

      猜你喜欢
      • 2021-11-22
      • 2021-03-03
      • 1970-01-01
      • 2017-06-25
      • 2018-09-02
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      • 2023-01-23
      相关资源
      最近更新 更多