การเรียกซ้ำใน Python
ในการเขียนโปรแกรม มีแนวคิดที่เรียกว่า การเรียกซ้ำ (recursion) - เมื่อฟังก์ชันเรียก ตัวเอง
ตัวอย่าง . การเรียกซ้ำอย่างง่ายพร้อมตัวนับ
มาแสดงตัวเลขตั้งแต่ 1 ถึง 10 ด้วยการเรียกซ้ำกัน:
i = 1
def func():
global i
print(i)
i += 1
if i <= 10:
func() # ฟังก์ชันเรียกตัวเองที่นี่
func()
มาพูดคุยกันว่าคำสั่งนี้ทำงานอย่างไร
เรามีตัวแปรโกลบอล i
และฟังก์ชัน func ภายในซึ่ง
แสดงเนื้อหาของตัวแปร
i ไปยังคอนโซล จากนั้นจึงบวก
หนึ่งเข้าไป
หากตัวแปร i ของเราน้อยกว่า
หรือเท่ากับ 10 ฟังก์ชันจะถูกเรียก
ซ้ำอีกครั้ง เนื่องจากตัวแปร i -
เป็นตัวแปรโกลบอล ดังนั้นในแต่ละการเรียกฟังก์ชันใหม่
ค่าในตัวแปร i ที่กำหนดไว้ในการเรียกก่อนหน้า
จะถูกนำมาใช้
ผลลัพธ์คือ ฟังก์ชันจะเรียกตัวเอง
จนกว่า i จะมากกว่า
10
โปรดทราบว่า ในกรณีของเราเราไม่สามารถรันฟังก์ชัน
โดยไม่มี if ได้ - หากทำเช่นนั้น
จะทำให้เกิดการเรียกฟังก์ชันที่ไม่สิ้นสุด
ตัวอย่าง . การเรียกซ้ำสำหรับการแสดงองค์ประกอบในลิสต์ซ้อน
การเรียกซ้ำมักถูกใช้บ่อยที่สุดสำหรับ การวนซ้ำผ่านลิสต์ที่มีระดับการซ้อนที่แตกต่างกัน สมมติว่าเรามีลิสต์ต่อไปนี้:
lst = [1, [2, 3], [[4, 5], [6, 7, 8, [9]]]]
มาสร้างฟังก์ชันที่จะวนซ้ำผ่านมันกัน
ในนั้นจำเป็นต้องกำหนดเงื่อนไขก่อน
เพื่อให้องค์ประกอบที่เป็น primitive
เช่น ตัวเลขที่ดึงมาจากลิสต์
แสดงในคอนโซล และหากองค์ประกอบเป็น
ออบเจกต์ที่ซับซ้อน เช่น ลิสต์ซ้อน
ให้ในกรณีนี้ฟังก์ชันเรียกตัวเอง
นั่นคือจะเกิดการเรียกซ้ำขึ้น สำหรับการตรวจสอบ
ประเภทขององค์ประกอบ เราจะใช้ฟังก์ชัน isinstance
เฉพาะสำหรับตัวอย่างของเราในพารามิเตอร์แรก
ของ isinstance เราจะเขียน el และ
ตัวที่สอง - ประเภท list:
def func(lst):
for el in lst:
if isinstance(el, list):
func(el)
else:
print(el)
เมื่อเรียกฟังก์ชัน จะแสดงตัวเลขทั้งหมด จากลิสต์ซ้อน:
func(lst) # จะแสดง 1, 2, ... 8, 9
ตัวอย่าง . การเรียกซ้ำสำหรับการดำเนินการกับองค์ประกอบในลิสต์ซ้อน
การเรียกซ้ำสามารถนำมาใช้สำหรับการดำเนินการต่างๆ กับองค์ประกอบในลิสต์ซ้อนได้ สมมติว่าเรามีลิสต์ต่อไปนี้:
lst = [1, [2, 3], [[4, 5], [6, 7, 8, [9]]]]
มาหาผลรวมขององค์ประกอบทั้งหมดกัน
สำหรับสิ่งนี้ในฟังก์ชันให้ประกาศตัวแปร res
ซึ่งจะสะสมผลรวมของตัวเลข
ในเงื่อนไขเราจะเขียนว่า หากองค์ประกอบ
เป็นออบเจกต์ที่ซับซ้อน มันจะเข้าสู่
พารามิเตอร์ของฟังก์ชัน func และถูกบวก
เข้ากับผลรวม นั่นหมายความว่าองค์ประกอบจะ
อยู่ในสภาวะเรียกซ้ำจนกว่าจะกลายเป็น
primitive และในกรณีนี้มันจะแค่
ถูกบวกเข้ากับผลรวมที่บันทึกไว้ใน res:
def func(lst):
res = 0
for el in lst:
if isinstance(el, list):
res += func(el)
else:
res += el
return res
มาเรียกฟังก์ชันและแสดงผลลัพธ์ของมัน ในคอนโซลกัน:
print(func(lst)) # จะแสดง 45
ตัวอย่าง . การเรียกซ้ำสำหรับการสะสมในลิสต์
ด้วยการเรียกซ้ำเราสามารถแยกลิสต์ซ้อน ให้เป็นลิสต์หนึ่งมิติเดียวได้ สมมติว่าเรา มีลิสต์ต่อไปนี้:
lst = [1, [2, 3], [[4, 5], [6, 7, 8, [9]]]]
มาเขียนในฟังก์ชันลิสต์ว่าง
res ซึ่งจะสะสม
องค์ประกอบจากลิสต์เริ่มต้น ต่อไปเราจะรัน
ลูปและกำหนดเงื่อนไข - หากองค์ประกอบ
เป็นลิสต์ มันจะเข้าสู่เมธอด
extend เมธอดนี้เชื่อมต่อ
องค์ประกอบของลิสต์หนึ่งไปที่ท้ายของลิสต์ที่สอง
นั่นคือองค์ประกอบของลิสต์ซ้อน
จะไปที่ท้ายลิสต์ res:
def func(lst):
res = []
for el in lst:
if isinstance(el, list):
res.extend(func(el))
else:
res.append(el)
return res
print(func(lst))
ผลลัพธ์ของโค้ดที่รัน:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
โจทย์ฝึกปฏิบัติ
แสดงองค์ประกอบที่เป็นตัวเลขทั้งหมดของดิกชันนารี ที่มีระดับการซ้อนใดๆ:
{
'a': {
'b': 1,
'c': 2,
'd': {
'e': 3,
'f': 4
}
},
'j': {
'h': 5,
'k': 6,
},
'l': 7
}
หาผลรวมขององค์ประกอบจากดิกชันนารีในโจทย์ ก่อนหน้า
รับลิสต์ขององค์ประกอบที่เป็น primitive จากดิกชันนารีในโจทย์ก่อนหน้า