Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

ฟังก์ชัน Python สร้าง Iterator สำหรับลูปที่มีประสิทธิภาพ (itertools)

เหมือนภาษาโปรแกรมมิ่งส่วนใหญ่ Python มีคำสั่ง while และ for เพื่อสร้างโครงสร้างลูป คำสั่ง for มีประโยชน์โดยเฉพาะสำหรับการเดินทางผ่าน iterables เช่น ลิสต์, ทูเพิล หรือสตริง เครื่องมือการวนซ้ำที่มีประสิทธิภาพและรวดเร็วยิ่งขึ้นถูกกำหนดในโมดูล itertools ของไลบรารีมาตรฐาน Python บล็อกสร้าง iterator นี้เป็นการนำไปใช้แบบ Pythonic ของเครื่องมือคล้ายกันในภาษาโปรแกรมมิ่งเชิงฟังก์ชันเช่น Haskell และ SML

ฟังก์ชันในโมดูล itertools มี 3 ประเภท:

  • Infinite iterators (ตัววนซ้ำอนันต์)
  • Finite iterators (ตัววนซ้ำจำกัด)
  • Combinatoric iterators (ตัววนซ้ำแบบจัดหมู่)

ฟังก์ชันต่อไปนี้สร้างลำดับอนันต์:

count() - ฟังก์ชันนี้คืนค่า iterator ของค่าที่มีระยะห่างเท่ากันจากค่าเริ่มต้น ฟังก์ชันนี้สามารถมีค่า step ตัวเลือกเพื่อเพิ่มค่าต่อไปโดยช่วงนี้:

>>> from itertools import count
>>> for x in count(20):
...     print(x)
>>> for x in count(100, 10):
...     print(x)

คำสั่งแรกจะสร้างลำดับอนันต์เริ่มจาก 20 และคำสั่งที่สองจะสร้างตัวเลขจาก 100 ด้วยความถี่ขั้น 10 สังเกตว่าลูปเป็นอนันต์และจะไม่สิ้นสุดด้วยตัวเอง จะสิ้นสุดเมื่อกด Ctrl-C

cycle() - ฟังก์ชันนี้เริ่มคืนค่าแต่ละองค์ประกอบจาก iterable ที่ให้มา และเก็บสำเนาไว้ เมื่อองค์ประกอบหมด องค์ประกอบในสำเนาจะถูกคืนค่า ทำให้เกิดลูปอนันต์:

>>> from itertools import cycle
>>> for x in cycle("hello"):
...     print(x)

ตัวอักษรในสตริงจะถูกพิมพ์ซ้ำๆ จนกว่าจะมีการหยุดด้วย Ctrl-C

repeat() - ฟังก์ชันนี้คืนค่าอาร์กิวเมนต์อ็อบเจ็กต์ซ้ำๆ หากอาร์กิวเมนต์ที่สอง 'times' ถูกให้มา การซ้ำจะเกิดขึ้นจำนวนครั้งนั้น:

>>> from itertools import repeat
>>> for x in repeat(1):
...     print(x)
>>> for x in repeat('hello', 10):
...     print(x)

ลูปแรกจะพิมพ์ 1 อย่างไม่รู้จบ ลูปที่สองพิมพ์ 'hello' 10 ครั้ง

ฟังก์ชันในหมวดหมู่ต่อไปนี้คืนค่า finite iterators ที่สิ้นสุดลงบนลำดับอินพุตที่สั้นที่สุด:

accumulate() - ฟังก์ชันนี้มี 2 พารามิเตอร์ ตัวแรกคือ iterable (ลิสต์, ทูเพิล หรือสตริง) พารามิเตอร์ที่สองค่าเริ่มต้นคือ operator.add() (ฟังก์ชันในโมดูล operator นำไปใช้กับออปเปอเรเตอร์บวกมาตรฐาน) แต่อาจเป็นฟังก์ชันอื่นที่รับพารามิเตอร์ตัวเลข 2 ตัว:

accumulate(sequence, func)

องค์ประกอบ 2 ตัวแรกของลำดับอินพุทถูกประมวลผลโดย func ผลลัพธ์ของการประมวลผลเป็นพารามิเตอร์แรกสำหรับรอบถัดไป และพารามิเตอร์ที่สองของ func คือองค์ประกอบที่ 3 ในลำดับอินพุท กระบวนการนี้ทำซ้ำจนลำดับหมด ฟังก์ชัน accumulate คืนค่า iterator ที่แต่ละองค์ประกอบเป็นผลลัพธ์สะสมของการประมวลผลองค์ประกอบติดต่อกัน

ในตัวอย่างต่อไปนี้ ตัวเลขในลิสต์ถูกบวกสะสม สังเกตว่าอาร์กิวเมนต์ฟังก์ชันค่าเริ่มต้นคือการดำเนินการบวก:

>>> from itertools import accumulate
>>> list(accumulate([1, 2, 3, 4, 5]))
[1, 3, 6, 10, 15]

เราสามารถมีฟังก์ชันที่กำหนดเองเป็นพารามิเตอร์ที่สองของ accumulate():

>>> def multiply(x, y):
...     return x * y
>>> list(accumulate([1, 2, 3, 4, 5], multiply))
[1, 2, 6, 24, 120]

พฤติกรรมนี้คล้ายกับฟังก์ชันสำเร็จรูป reduce() ฟังก์ชัน reduce() คืนค่าเฉพาะผลลัพธ์สุดท้ายของการสะสม ในขณะที่ accumulate() สร้าง iterator ของผลลัพธ์ระหว่างทางทั้งหมด

chain() - ฟังก์ชันนี้สามารถมี iterables มากกว่าหนึ่งเป็นพารามิเตอร์ มัน yield แต่ละองค์ประกอบของ iterable แรกเข้า iterator ผลลัพธ์ และดำเนินต่อไปจนกว่าพารามิเตอร์ iterable จะหมด:

>>> from itertools import chain
>>> list(chain([10, 20], 'hello', range(4)))
[10, 20, 'h', 'e', 'l', 'l', 'o', 0, 1, 2, 3]

dropwhile() - ฟังก์ชันนี้คืนค่า iterator โดยการ drop องค์ประกอบจาก iterable นานเท่าที่ฟังก์ชัน predicate อาร์กิวเมนต์คืนค่า true ทันทีที่ฟังก์ชันคืนค่า false องค์ประกอบที่เหลือทั้งหมดจะถูก yield ให้ iterator:

>>> from itertools import dropwhile
>>> def iseven(x):
...     if x % 2 == 0:
...         return True
...     else:
...         return False
>>> list(dropwhile(iseven, [12, 90, 61, 4, 15]))
[61, 4, 15]

filterfalse() - ฟังก์ชันนี้คืนค่า iterator โดยการกรององค์ประกอบที่ฟังก์ชัน predicate ให้ผลเป็น False:

>>> from itertools import filterfalse
>>> def iseven(x):
...     if x % 2 == 0:
...         return True
...     else:
...         return False
>>> list(filterfalse(iseven, [12, 90, 61, 4, 15]))
[61, 15]

islice() - ฟังก์ชันนี้สร้าง iterator โดยการเลือกองค์ประกอบบางส่วนจาก iterable เกณฑ์การเลือกขึ้นอยู่กับพารามิเตอร์ start, stop และ step การเลือกเริ่มจากค่า start และดำเนินต่อจนถึงค่า stop หาก stop เป็น None จะไปจนถึงท้าย iterable มิฉะนั้น การเลือกจะหยุดที่ดัชนีที่ระบุ พารามิเตอร์ step ค่าเริ่มต้นคือ 1 การเลือกองค์ประกอบเพิ่มขึ้นตามพารามิเตอร์ step ไม่มีพารามิเตอร์ใดที่สามารถเป็นลบได้:

>>> from itertools import islice
>>> list(islice(range(10), 1, 5, 2))
[1, 3]
>>> list(islice(range(10), 0, None, 3))
[0, 3, 6, 9]
>>> list(islice(range(10), 5, None))
[5, 6, 7, 8, 9]
>>> list(islice(range(10), 5))
[0, 1, 2, 3, 4]

ฟังก์ชันต่อไปนี้สร้าง Combinatoric iterators จากอ็อบเจ็กต์ iterable:

product() - ฟังก์ชันนี้สร้าง iterator ซึ่งเป็น Cartesian product ขององค์ประกอบในลำดับอินพุท นี่เทียบเท่ากับการสร้าง nested for loops หนึ่งสำหรับการเดินทางแต่ละ iterable sequence:

ในตัวอย่างต่อไปนี้ เทคนิค list comprehension ถูกใช้เพื่อรัน nested loops 2 ชั้นบน 2 ลำดับเพื่อสร้าง Cartesian product:

>>> [[x, y] for x in [1, 2, 3] for y in ['a', 'b', 'c']]
[[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c'], [3, 'a'], [3, 'b'], [3, 'c']]

ฟังก์ชัน product() ให้ผลลัพธ์คล้ายกัน:

>>> from itertools import product
>>> list(product([1, 2, 3], ['a', 'b', 'c']))
[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (3, 'a'), (3, 'b'), (3, 'c')]

permutations() - ฟังก์ชันนี้ yield ทุก permutation ที่เป็นไปได้ขององค์ประกอบใน iterable อินพุท ความยาวของแต่ละ permutation อาจระบุเป็นพารามิเตอร์ที่สอง หากไม่ระบุ ความยาวคือ 1:

>>> list(permutations(range(1, 4), 2))
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

combinations() - ฟังก์ชันนี้ yield ทุก combination ที่เป็นไปได้ขององค์ประกอบใน iterable อินพุท ความยาวของแต่ละ permutation อาจระบุเป็นพารามิเตอร์ที่สอง หากไม่ระบุ ความยาวคือ 1:

>>> from itertools import combinations
>>> list(combinations(range(1, 4), 2))
[(1, 2), (1, 3), (2, 3)]

บทความนี้แนะนำเครื่องมือ iterator ต่างๆ ที่กำหนดในโมดูล itertools ของไลบรารี Python