Contents

การใช้ฟังก์ชัน super() ในคลาส Python

ประเด็นที่สำคัญ

การใช้ฟังก์ชัน super() ของ Python ช่วยอำนวยความสะดวกในการเรียกใช้เมธอดภายในคลาสย่อยโดยการเข้าถึงซูเปอร์คลาส ดังนั้นจึงปรับปรุงกระบวนการปรับใช้การสืบทอดและการแทนที่เมธอดในลักษณะที่หรูหรา

ฟังก์ชัน super() มีความเชื่อมโยงที่สำคัญกับ Method Resolution Order (MRO) ใน Python ซึ่งควบคุมลำดับที่คลาสบรรพบุรุษจะถูกพิจารณาอย่างละเอียดเพื่อหาเมธอดและคุณสมบัติระหว่างการแก้ไขเมธอด

การใช้ super() ภายใน Constructor ของคลาสเป็นแนวทางทั่วไปสำหรับการสร้างคุณลักษณะที่ใช้ร่วมกันในคลาสพาเรนต์ ในขณะเดียวกันก็กำหนดคุณลักษณะเฉพาะในคลาสรองด้วย ความล้มเหลวในการใช้งาน super() อาจส่งผลให้เกิดผลลัพธ์ที่ไม่พึงประสงค์ รวมถึงการละเว้นการเริ่มต้นแอตทริบิวต์

ลักษณะพื้นฐานประการหนึ่งของภาษาการเขียนโปรแกรม Python คือกระบวนทัศน์การเขียนโปรแกรมเชิงวัตถุ (OOP) ซึ่งช่วยให้สามารถสร้างแบบจำลองที่แสดงถึงวัตถุในชีวิตจริงและการเชื่อมต่อระหว่างกันในลักษณะที่มีโครงสร้าง

ในบริบทของการเขียนโปรแกรมด้วย Python เป็นเรื่องปกติที่จะใช้การสืบทอดเพื่อแก้ไขหรือแทนที่คุณสมบัติหรือฟังก์ชันของเอนทิตีหลักของคลาส ภาษามีกลไกที่สะดวกสบายที่เรียกว่าฟังก์ชัน"super()“ซึ่งช่วยให้สามารถเรียกเมธอดของคลาสที่เหนือกว่าจากภายในคลาสรองได้

super() คืออะไร และเหตุใดคุณจึงต้องการมัน

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

เพื่อที่จะใช้ประโยชน์จากคุณลักษณะและวิธีการของซูเปอร์คลาสในการเขียนโปรแกรมเชิงวัตถุ เราอาจจะใช้ฟังก์ชัน super() ฟังก์ชันนี้มีบทบาทสำคัญในเนื่องจากอำนวยความสะดวกในการใช้งานการสืบทอดและการแทนที่เมธอด ซึ่งเป็นแนวคิดพื้นฐานในการเขียนโปรแกรมเชิงวัตถุ

ซุปเปอร์() ทำงานอย่างไร?

ภายใน พฤติกรรมของฟังก์ชัน super() นั้นเกี่ยวพันกับแนวคิดของ Method Resolution Order (MRO) ซึ่งเป็นกลไกที่กำหนดโดยอัลกอริทึม C3 linearization ใน Python

นี่คือวิธีการทำงานของ super():

เมื่อเรียก super() ภายในวิธีการของคลาสย่อยใน Python ภาษาจะระบุทั้งคลาสปัจจุบันโดยอัตโนมัติซึ่งมีวิธีการเรียกใช้ เช่นเดียวกับอินสแตนซ์ของคลาสดังกล่าวที่แสดงโดย self

⭐ กำหนดซูเปอร์คลาส: super() รับสองอาร์กิวเมนต์€”คลาสปัจจุบันและอินสแตนซ์€”ซึ่งคุณไม่ต้องการ ให้ผ่านไปได้อย่างชัดเจน ใช้ข้อมูลนี้เพื่อกำหนดซูเปอร์คลาสเพื่อมอบหมายการเรียกเมธอด ซึ่งทำได้โดยการตรวจสอบลำดับชั้นของชั้นเรียนและ MRO

เมื่อซุปเปอร์คลาสถูกระบุแล้ว ฟังก์ชัน super() จะอนุญาตให้เรียกใช้เมธอดของมันราวกับว่ามันถูกเรียกโดยตรงจากคลาสย่อย ความสามารถนี้อำนวยความสะดวกทั้งการขยายและการแทนที่วิธีการของซูเปอร์คลาส ขณะเดียวกันก็ใช้ประโยชน์จากการใช้งานดั้งเดิมที่จัดทำโดยซูเปอร์คลาส

การใช้ super() ในตัวสร้างคลาส

การผสมผสานการใช้เมธอด super() ภายในตัวสร้างของคลาสเป็นวิธีการที่แพร่หลาย เนื่องจากช่วยให้สามารถเริ่มต้นคุณสมบัติที่ใช้ร่วมกันระหว่างคลาสพี่น้อง ในขณะเดียวกันก็อนุญาตให้มีคุณลักษณะเฉพาะในลูกหลานแต่ละคน

เพื่อแสดงให้เห็นแนวคิดของการสืบทอดในการเขียนโปรแกรมเชิงวัตถุโดยใช้ Python เราสามารถสร้างคลาส “Father” ที่ทำหน้าที่เป็นคลาสพื้นฐานสำหรับคลาสอื่นที่เรียกว่า “Son” คลาส “Son” จะสืบทอดคุณสมบัติและวิธีการจากคลาสแม่ ซึ่งก็คือ “Father” ซึ่งแสดงให้เห็นว่าการสืบทอดช่วยให้สามารถนำโค้ดกลับมาใช้ใหม่และความเป็นโมดูลได้อย่างไร

 class Father:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

class Son(Father):
    def __init__(self, first_name, last_name, age, hobby):
        # Call the parent class constructor (Father)
        super().__init__(first_name, last_name)

        self.age = age
        self.hobby = hobby

    def get_info(self):
        return f"Son's Name: {self.first_name} {self.last_name}, \
Son's Age: {self.age}, Son's Hobby: {self.hobby}"

# Create an instance of the Son class
son = Son("Pius", "Effiong", 25, "Playing Guitar")

# Access attributes
print(son.get_info())

ภายในขอบเขตของคอนสตรัคเตอร์ของคลาส Son ความจำเป็นในการเรียกการอุปถัมภ์ของคลาสแม่นั้นจะดำเนินการผ่านการกระทำอันมหัศจรรย์ของการเรียกฟังก์ชัน super() การดำเนินการที่สำคัญนี้กระตุ้นให้เกิดการเริ่มต้นของตัวสร้างคลาส พ่อ ที่เป็นบิดา โดยเสนอตัวระบุที่สำคัญยิ่งที่นับถือสองตัวในรูปแบบของตัวแปร first\_name และ Last\_name ในลักษณะนี้ ชนชั้น"พ่อ"ยังคงรักษาความสามารถในการบรรลุและกำหนดการกำหนดชื่อเหล่านี้ได้อย่างถูกต้อง แม้ว่าจะมีลักษณะเป็น"บุตร"ก็ตาม

/th/images/using-super-in-class-constructor.jpg

ในกรณีที่ไม่ได้เรียกใช้เมธอด super() ภายในโครงสร้าง

 ...
class Son(Father):
    def __init__(self, first_name, last_name, age, hobby):
        self.age = age
        self.hobby = hobby
...

ในกรณีที่คุณพยายามเรียกใช้เมธอด get\_info ในช่วงหัวเลี้ยวหัวต่อนี้ จะส่งผลให้เกิดการสร้าง AttributeError เนื่องจากยังไม่ได้เตรียมใช้งานแอตทริบิวต์ self.first\_name และ self.last\_name

/th/images/trying-to-use-parent-attributes-without-super.jpg

การใช้ super() ใน Class Method

เราสามารถใช้ฟังก์ชัน super() ไม่เพียงแต่ภายในขอบเขตของขั้นตอนการสร้างเท่านั้น แต่ยังรวมถึงวิธีการที่หลากหลายเพื่อเพิ่มหรือแทนที่ฟังก์ชันการทำงานของแนวทางระเบียบวิธีของคลาสผู้ปกครองด้วย

 class Father:
    def speak(self):
        return "Hello from Father"

class Son(Father):
    def speak(self):
        # Call the parent class's speak method using super()
        parent_greeting = super().speak()
        return f"Hello from Son\n{parent_greeting}"

# Create an instance of the Son class
son = Son()

# Call the speak method of the Son class
son_greeting = son.speak()

print(son_greeting)

คลาส Son ใน Python ได้รับการออกแบบมาเพื่อสืบทอดคุณสมบัติและวิธีการจากคลาสพาเรนต์หรือคลาส Father รวมถึงเมธอด speak() ด้วยการใช้ฟังก์ชัน super().speak() ภายในเมธอด พูด() ของคลาส Son จะทำให้สามารถเรียกใช้เมธอด พูด () ดั้งเดิมของคลาส Father ได้อย่างมีประสิทธิภาพ ข้อมูลเพิ่มเติมหรือข้อความเฉพาะของคลาส Son

/th/images/using-super-in-class-mthod.jpg

ในกรณีที่เมธอดแทนที่เมธอดอื่นโดยไม่ใช้ฟังก์ชัน super() ที่ให้มา ฟังก์ชันที่ต้องการจากคลาสพาเรนต์จะไม่ถูกดำเนินการ ด้วยเหตุนี้ จึงอาจส่งผลให้เกิดพฤติกรรมที่ไม่ได้ตั้งใจอันเนื่องมาจากวิธีการใหม่และแตกต่างโดยสิ้นเชิงที่มาแทนที่ฟังก์ชันการทำงานแบบเดิม

ทำความเข้าใจลำดับการแก้ปัญหาวิธีการ

Method Resolution Order (MRO) หมายถึงลำดับชั้นของลำดับความสำคัญที่กำหนดลำดับที่ Python จะค้นหาวิธีการและคุณลักษณะเมื่อต้องจัดการกับโครงสร้างคลาสที่ซับซ้อนที่เกี่ยวข้องกับการสืบทอดหลายรายการ กลไกนี้ช่วยให้แน่ใจว่ามีการเรียกวิธีการที่เหมาะสมตามตัวเลือกที่มีอยู่ภายในคลาสพาเรนต์ที่เกี่ยวข้อง ดังนั้นจึงแก้ไขความคลุมเครือที่อาจเกิดขึ้นจากคำจำกัดความที่ทับซ้อนกัน

 class Nigeria():
    def culture(self):
        print("Nigeria's culture")

class Africa():
   def culture(self):
       print("Africa's culture") 

เมื่อสร้างตัวอย่างคลาสลากอสและเรียกใช้วิธีการเพาะเลี้ยง เหตุการณ์จำนวนหนึ่งเกิดขึ้นซึ่งมีส่วนช่วยในการทำงานโดยรวมของวัตถุ การเรียกใช้โค้ดดำเนินการผ่านหลายขั้นตอนที่เกี่ยวข้องกับการจัดการข้อมูล การดึงข้อมูลจากแหล่งภายนอก และการประยุกต์ใช้อัลกอริธึมต่างๆ เพื่อวิเคราะห์แง่มุมทางวัฒนธรรมตามพารามิเตอร์อินพุตที่ผู้ใช้ให้มาหรือค่าเริ่มต้นที่ตั้งไว้ใน Constructor ผลลัพธ์ที่ได้คือการประเมินคุณลักษณะทางวัฒนธรรมของเมืองที่ระบุอย่างครอบคลุมตามประเภทลากอส

Python จะค้นหาเมธอด culture ภายในคลาส Lagos ก่อน ในกรณีที่ค้นพบวิธีการนี้และพร้อมใช้งาน อัลกอริธึมจะดำเนินการเรียกใช้ต่อไป อย่างไรก็ตาม หากไม่มีวิธีการดังกล่าวหรือไม่สามารถเข้าถึงได้ กระบวนการก็จะเข้าสู่ขั้นตอนต่อไป

ถ้าคลาส Lagos ไม่มีเมธอด culture() Python จะค้นหาเมธอดในคลาสพื้นฐานของลำดับชั้นของคลาส โดยเริ่มจากคลาสที่อยู่ในรายการหลังเครื่องหมายทวิภาค ( : ) ซึ่งสืบทอดมาจาก คลาส"ลากอส"ในตัวอย่างนี้ คลาส Lagos ได้รับการกำหนดให้รับช่วงแรกจากคลาส’Africa และลำดับที่สองจากคลาส'Nigeria ดังนั้น หากคลาส Lagos ไม่มีการนำเมธอด culture() มาใช้ Python จะพยายามค้นหาวิธีการภายในคลาส Africa ก่อนที่จะค้นหาคลาส Nigeria

การค้นหาวิธีการเฉพาะทางวัฒนธรรมภายในลำดับชั้นที่กำหนดจะดำเนินการผ่านชุดของชั้นเรียนที่ซ้อนกัน โดยแต่ละชั้นเรียนที่ตามมาจะถูกตรวจสอบในกรณีที่พบวิธีการที่ต้องการในนั้น ในกรณีที่ไม่พบวิธีการในระดับเริ่มต้นของการสอบถาม เช่น คลาสแอฟริกัน Python จะเปลี่ยนโฟกัสไปที่คลาสสูงสุดถัดไปในโครงสร้างลำดับชั้น ซึ่งในกรณีนี้จะสอดคล้องกับคลาสไนจีเรีย กระบวนการนี้จะเกิดขึ้นซ้ำอีกครั้งเมื่อลงจากแผนผังคลาส โดยขยายจากทั่วไปที่สุดไปสู่เฉพาะเจาะจงน้อยที่สุด จนกระทั่งถึงเวลาที่เมธอดที่ต้องการไม่สามารถอยู่ในซูเปอร์คลาสใด ๆ ที่พบได้ ในช่วงหัวเลี้ยวหัวต่อนั้น มีการยกข้อยกเว้นขึ้นเพื่อระบุผลลัพธ์การค้นหาที่ไม่ประสบผลสำเร็จ

/th/images/the-mothod-resolution-order.jpg

ลำดับการแก้ปัญหาวิธีการ (MRO) สำหรับลากอสจะแสดงเป็นเส้นตรง โดยเริ่มจากด้านซ้ายและเลื่อนไปทางขวา

ข้อผิดพลาดทั่วไปและแนวทางปฏิบัติที่ดีที่สุด

เมื่อใช้ฟังก์ชัน super() สิ่งสำคัญคือต้องระวังข้อผิดพลาดที่อาจเกิดขึ้นเพื่อให้แน่ใจว่าจะได้รับประสบการณ์ที่ราบรื่นและมีประสิทธิภาพ

⭐ โปรดคำนึงถึงลำดับการแก้ไขวิธีการ โดยเฉพาะอย่างยิ่งในสถานการณ์การสืบทอดหลายรายการ หากคุณต้องการใช้การสืบทอดหลายรายการที่ซับซ้อน คุณควรคุ้นเคยกับ อัลกอริธึม C3 Linearization ที่ Python ใช้ในการกำหนด MRO

ควรหลีกเลี่ยงการพึ่งพาแบบวงกลมภายในลำดับชั้นของคลาส เนื่องจากอาจส่งผลให้เกิดพฤติกรรมที่ไม่แน่นอนและคาดเดาได้ยาก

เมื่อทำงานกับลำดับชั้นของคลาสที่ซับซ้อนซึ่งเกี่ยวข้องกับการใช้ฟังก์ชัน super() สิ่งสำคัญคือต้องรักษา codebase ที่ชัดเจนและมีการบันทึกไว้อย่างดี สิ่งนี้ไม่เพียงแต่รับประกันการทำงานที่เหมาะสม แต่ยังส่งเสริมความเข้าใจในหมู่นักพัฒนาคนอื่นๆ ที่อาจจำเป็นต้องดำเนินการหรือแก้ไขโค้ดในอนาคต ด้วยการแสดงความคิดเห็นที่กระชับแต่ให้ข้อมูล คุณสามารถเพิ่มความสามารถในการอ่านและการบำรุงรักษาโครงการของคุณ อำนวยความสะดวกในการทำงานร่วมกัน และลดข้อผิดพลาดหรือความสับสนที่อาจเกิดขึ้น

ใช้ super() อย่างถูกวิธี

การใช้ฟังก์ชัน super() ของ Python แสดงถึงแง่มุมที่ขาดไม่ได้ของกระบวนทัศน์การเขียนโปรแกรมเชิงวัตถุ โดยเฉพาะอย่างยิ่งในส่วนที่เกี่ยวข้องกับการอำนวยความสะดวกในการสืบทอดและการแทนที่เมธอด การเข้าใจความซับซ้อนที่เกี่ยวข้องกับเอนทิตีการทำงานนี้และการปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดที่กำหนดไว้ช่วยให้สามารถพัฒนาแอปพลิเคชันซอฟต์แวร์ที่ยั่งยืนและมีทรัพยากรมากขึ้นภายในระบบนิเวศของ Python