เพื่อให้เข้าใจการปิดของ python ดีขึ้น อันดับแรกให้เข้าใจก่อนว่าฟังก์ชันที่ซ้อนกันและคลาสของ python คืออะไร กล่าวโดยย่อ การปิด python ยังเป็นฟังก์ชันที่ห่อหุ้มข้อมูลด้วยโค้ด
ฟังก์ชันที่ซ้อนกันของ Python
ฟังก์ชันที่กำหนดไว้ภายในฟังก์ชันอื่นเรียกว่าฟังก์ชันที่ซ้อนกัน ฟังก์ชันที่ซ้อนกันสามารถเข้าถึงตัวแปรของขอบเขตที่ล้อมรอบได้
def funcOut(): print("This is outer function.") def funcIn(): print("This function is defined inside funcOut. \nThis function(funcIn) is called\ nested function.") print("We can call nested function here.") funcIn() print("We are in outer function.\nCalling funcOut.") funcOut()
ผลลัพธ์
We are in outer function. Calling funcOut. This is outer function. We can call nested function here. This function is defined inside funcOut. This function(funcIn) is called nested function.
ดังนั้น funcIn จึงเป็นฟังก์ชันที่ซ้อนกันซึ่งกำหนดไว้ใน funcOut เมื่อดูผลลัพธ์ข้างต้น เราจะเข้าใจลำดับการเรียกใช้ของฟังก์ชันต่างๆ ได้
ในกรณีที่เราต้องการให้มีฟังก์ชันทั้งหมดของ funcIn จาก funcOut เพื่อที่เราจะต้องทำ "return funcIn" ในโปรแกรมด้านบนนี้ เรียกว่า closure ใน python
กล่าวโดยย่อ การปิดเป็นฟังก์ชัน (วัตถุ) ที่จดจำสภาพแวดล้อมการสร้าง (ขอบเขตที่ล้อมรอบ)
def closureFunc(start): def incrementBy(inc): return start + inc return incrementBy closure1 = closureFunc(9) closure2 = closureFunc(90) print ('clsure1(3) = %s' %(closure1(3))) print ('closure2(3) = %s' %(closure2(3)))
ผลลัพธ์
clsure1(3) = 12 closure2(3) = 93
การเรียกตัวแปร closure1 (ซึ่งเป็นประเภทฟังก์ชัน) ด้วย closure1(3) จะกลับมาเป็น 12 ในขณะที่ closure2(3) จะคืนค่า 93 ในขณะที่ closure1 และ closure2 ต่างก็อ้างอิงถึงฟังก์ชันเดียวกัน incrementBy เรามีสองตัวแปรที่แตกต่างกัน closure1 &closure2 ซึ่ง ถูกผูกเข้าด้วยกันโดยตัวระบุ closureFunc ซึ่งนำไปสู่ผลลัพธ์ที่แตกต่างกัน
__closure__ attribute and cell objects
หากต้องการข้อมูลเพิ่มเติม เราสามารถใช้แอตทริบิวต์ __closure__ และวัตถุเซลล์:
def closureFunc(start): def incrementBy(inc): return start + inc return incrementBy a= closureFunc(9) b = closureFunc(90) print ('type(a)=%s' %(type(a))) print ('a.__closure__=%s' %(a.__closure__)) print ('type(a.__closure__[0])=%s' %(type(a.__closure__[0]))) print ('a.__closure__[0].cell_contents=%s' %(a.__closure__[0].cell_contents)) print ('type(b)=%s' %(type(b))) print ('b.__closure__=%s' %(b.__closure__)) print ('type(b.__closure__[0])=%s' %(type(b.__closure__[0]))) print ('b.__closure__[0].cell_contents=%s' %(b.__closure__[0].cell_contents))
ผลลัพธ์
type(a) = <class 'function'> a.__closure__ = <cell at 0x057F8490: int object at 0x68A65770> type(a.__closure__[0]) = <class 'cell'> a.__closure__[0].cell_contents = 9 type(b)=<class 'function'> b.__closure__ = <cell at 0x0580BD50: int object at 0x68A65C80> type(b.__closure__[0]) = <class 'cell'> b.__closure__[0].cell_contents=90
จากผลลัพธ์ข้างต้น เราจะเห็นแต่ละเซลล์ของออบเจ็กต์เก็บค่าไว้ในขณะที่สร้างมันขึ้นมา