ฉันได้สร้างโค้ด Python เพื่อใช้คลาสภายนอกจากคลาสภายในโดยอาศัยความคิดที่ดีจากคำตอบอื่นสำหรับคำถามนี้ ฉันคิดว่ามันสั้นง่ายและเข้าใจง่าย
class higher_level__unknown_irrelevant_name__class:
def __init__(self, ...args...):
...other code...
subclasses = self._subclass_container()
self.some_subclass = subclasses["some_subclass"]
del subclasses
def sub_function(self, ...args...):
...other code...
def _subclass_container(self):
_parent_class = self
class some_subclass:
def __init__(self):
self._parent_class = _parent_class
class subclass_2:
def __init__(self):
self._parent_class = _parent_class
return {"some_subclass": some_subclass, "subclass_2": subclass_2}
รหัสหลัก "พร้อมใช้งานจริง" (ไม่มีความคิดเห็น ฯลฯ ) อย่าลืมแทนที่ค่าทั้งหมดในวงเล็บเหลี่ยม (เช่น<x>
) ด้วยค่าที่ต้องการ
class <higher_level_class>:
def __init__(self):
subclasses = self._subclass_container()
self.<sub_class> = subclasses[<sub_class, type string>]
del subclasses
def _subclass_container(self):
_parent_class = self
class <sub_class>:
def __init__(self):
self._parent_class = _parent_class
return {<sub_class, type string>: <sub_class>}
คำอธิบายวิธีการทำงานของวิธีนี้ (ขั้นตอนพื้นฐาน):
สร้างฟังก์ชันที่ตั้งชื่อ_subclass_container
เพื่อทำหน้าที่เป็น Wrapper เพื่อเข้าถึงตัวแปรself
ซึ่งเป็นการอ้างอิงไปยังคลาสระดับที่สูงกว่า (จากโค้ดที่ทำงานภายในฟังก์ชัน)
สร้างตัวแปรที่ตั้งชื่อ_parent_class
ซึ่งเป็นการอ้างอิงถึงตัวแปรself
ของฟังก์ชันนี้เพื่อให้คลาสย่อยของ_subclass_container
สามารถเข้าถึงได้ (หลีกเลี่ยงความขัดแย้งของชื่อกับself
ตัวแปรอื่นในคลาสย่อย)
ส่งคืนคลาสย่อย / คลาสย่อยเป็นพจนานุกรม / รายการเพื่อให้โค้ดที่เรียกใช้_subclass_container
ฟังก์ชันสามารถเข้าถึงคลาสย่อยภายในได้
ใน__init__
ฟังก์ชั่นภายในชั้นเรียนระดับที่สูงขึ้น (หรือที่ใดก็ตามที่จำเป็นอื่น ๆ ) ได้รับกลับมาย่อยชั้นเรียนจากฟังก์ชั่นลงในตัวแปร_subclass_container
subclasses
กำหนดคลาสย่อยที่จัดเก็บในsubclasses
ตัวแปรให้เป็นแอตทริบิวต์ของคลาสระดับสูงกว่า
เคล็ดลับในการทำให้สถานการณ์ง่ายขึ้น:
ทำให้รหัสเพื่อกำหนดคลาสย่อยให้กับคลาสระดับที่สูงขึ้นง่ายต่อการคัดลอกและใช้ในคลาสที่ได้มาจากคลาสระดับสูงกว่าที่มี __init__
การเปลี่ยนแปลงฟังก์ชัน:
แทรกก่อนบรรทัดที่ 12 ในรหัสหลัก:
def _subclass_init(self):
จากนั้นใส่ในฟังก์ชันบรรทัดที่ 5-6 (ของโค้ดหลัก) และแทนที่บรรทัดที่ 4-7 ด้วยรหัสต่อไปนี้:
self._subclass_init(self)
ทำให้การกำหนดคลาสย่อยให้กับคลาสระดับที่สูงขึ้นเป็นไปได้เมื่อมีคลาสย่อยจำนวนมาก / ไม่ทราบจำนวน
แทนที่บรรทัด 6 ด้วยรหัสต่อไปนี้:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
ตัวอย่างสถานการณ์ที่โซลูชันนี้จะเป็นประโยชน์และไม่ควรรับชื่อคลาสระดับสูงกว่า:
สร้างคลาสชื่อ "a" ( class a:
) มีคลาสย่อยที่ต้องเข้าถึง (พาเรนต์) คลาสย่อยหนึ่งเรียกว่า "x1" ในคลาสย่อยนี้โค้ดa.run_func()
จะถูกรัน
จากนั้นอีกชั้นหนึ่งชื่อ "b" จะถูกสร้างขึ้นมาจากคลาส "a" ( class b(a):
) หลังจากนั้นโค้ดบางส่วนจะทำงานb.x1()
(เรียกฟังก์ชันย่อย "x1" ของ b ซึ่งเป็นคลาสย่อยที่ได้รับมา) ฟังก์ชันนี้ทำงานa.run_func()
โดยเรียกฟังก์ชัน "run_func" ของคลาส "a" ไม่ใช่ฟังก์ชัน "run_func" ของพาเรนต์ "b" (ตามที่ควร) เนื่องจากฟังก์ชันที่กำหนดไว้ในคลาส "a" ถูกกำหนดให้อ้างถึง ไปยังฟังก์ชันของคลาส "a" เช่นเดียวกับที่เป็นพาเรนต์
สิ่งนี้จะทำให้เกิดปัญหา (เช่นหากฟังก์ชันa.run_func
ถูกลบไปแล้ว) และวิธีแก้ปัญหาเดียวที่ไม่มีการเขียนโค้ดในคลาสa.x1
ใหม่คือการกำหนดคลาสย่อยใหม่x1
ด้วยโค้ดที่อัปเดตสำหรับคลาสทั้งหมดที่ได้มาจากคลาส "a" ซึ่งเห็นได้ชัดว่าเป็นเรื่องยากและไม่คุ้มค่า มัน.