ฟังก์ชั่นแผนที่และการวนซ้ำใน 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/function.html#iterators ไม่ได้ช่วยอะไรมากนัก ฉันลองดูแล้วและคิดว่าอย่างน้อยหนึ่งบิตที่มีความคิดเห็นด้านล่าง (# <python code>) น่าจะได้ผล ฉันไม่ใช่นักพัฒนา Python ที่มีประสบการณ์ และฉันคิดว่าฉันขาด gotchas บางอย่างเกี่ยวกับไวยากรณ์/รูปแบบการทำงานของ 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