Fungsi peta dan iterable di python 3.6

Saya mewarisi sepotong kode yang perlu saya jalankan di tempat lain selain tempat aslinya dengan beberapa perubahan kecil. Saya mencoba map daftar string ke sesuatu yang menerapkan fungsi ke setiap elemen daftar itu menggunakan python 3.6 (bahasa yang tidak saya pahami).

Saya ingin menggunakan map bukan pemahaman daftar, tapi sekarang saya ragu ini mungkin.

Dalam contoh berikut saya telah mencoba kombinasi for loop, yield (atau tidak), dan next(...) atau tidak, tetapi saya tidak dapat membuat kode berfungsi seperti yang diharapkan.

Saya ingin melihat cetakannya:

AAA! xxx 
Found: foo
Found: bar

setiap kali penghitung xxx modulo 360 adalah 0 (nol).

Saya memahami fungsi map tidak mengeksekusi kode, jadi saya perlu melakukan sesuatu untuk "menerapkan" fungsi itu ke setiap elemen daftar input.

Namun saya tidak dapat membuat hal ini berhasil. Dokumentasi ini https://docs.python.org/3.6/library/functions.html#map dan https://docs.python.org/3.6/howto/function.html#iterators tidak banyak membantu, saya telah mempelajarinya dan menurut saya setidaknya satu dari bit komentar di bawah (# <python code>) seharusnya berfungsi. Saya bukan pengembang python berpengalaman dan saya rasa saya melewatkan beberapa pemahaman tentang sintaks/konvensi python 3.6 mengenai iterator/generator.

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()

Saya mendapatkan banyak kesalahan berbeda/perilaku tak terduga dari loop for saat menjalankan skrip:

  • tidak mencetak apa pun saat saya menelepon print(...)
  • TypeError: 'NoneType' object is not callable
  • AttributeError: 'map' object has no attribute 'next'
  • TypeError: 'NoneType' object is not iterable
  • Mencetak apa yang saya harapkan disisipkan oleh None, misalnya:
AAA! 3047040
Found: foo
None
Found: bar
None

person TPPZ    schedule 20.03.2018    source sumber


Jawaban (1)


Saya menemukan panggilan ke next(iterable_thingy) sebenarnya memanggil fungsi yang dipetakan.

Mengetahui panjang daftar input ketika memetakannya untuk menghasilkan iterable, berarti kita tahu berapa kali kita harus memanggil next(iterable_thingy), sehingga fungsi report_issue (dalam contoh saya sebelumnya) berjalan seperti yang diharapkan ketika didefinisikan seperti ini:

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)

Untuk memecahkan masalah hal-hal yang dapat diubah ini, saya menemukan berguna menjalankan ipython (REPL interaktif) untuk memeriksa jenis dan dokumentasi dari iterable yang dihasilkan, seperti ini:

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