Tôi đã tạo một số mã Python để sử dụng lớp ngoài từ lớp bên trong của nó , dựa trên một ý tưởng hay từ một câu trả lời khác cho câu hỏi này. Tôi nghĩ nó ngắn gọn, đơn giản và dễ hiểu.
class higher_level__unknown_irrelevant_name__class:
def __init__(self, ...args...):
...other code...
# Important lines to access sub-classes.
subclasses = self._subclass_container()
self.some_subclass = subclasses["some_subclass"]
del subclasses # Free up variable for other use.
def sub_function(self, ...args...):
...other code...
def _subclass_container(self):
_parent_class = self # Create access to parent class.
class some_subclass:
def __init__(self):
self._parent_class = _parent_class # Easy access from self.
# Optional line, clears variable space, but SHOULD NOT BE USED
# IF THERE ARE MULTIPLE SUBCLASSES as would stop their parent access.
# del _parent_class
class subclass_2:
def __init__(self):
self._parent_class = _parent_class
# Return reference(s) to the subclass(es).
return {"some_subclass": some_subclass, "subclass_2": subclass_2}
Mã chính, "sẵn sàng sản xuất" (không có chú thích, v.v.). Hãy nhớ thay thế tất cả từng giá trị trong dấu ngoặc nhọn (ví dụ <x>
) bằng giá trị mong muốn.
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>}
Giải thích về cách hoạt động của phương pháp này (các bước cơ bản):
Tạo một hàm có tên _subclass_container
để hoạt động như một trình bao bọc để truy cập vào biến self
, một tham chiếu đến lớp cấp cao hơn (từ mã chạy bên trong hàm).
Tạo một biến có tên _parent_class
là một tham chiếu đến biến self
của hàm này, mà các lớp con của _subclass_container
có thể truy cập (tránh xung đột tên với các self
biến khác trong lớp con).
Trả về lớp con / lớp con dưới dạng từ điển / danh sách để mã gọi _subclass_container
hàm có thể truy cập các lớp con bên trong.
Trong __init__
hàm bên trong lớp cấp cao hơn (hoặc bất cứ nơi nào khác cần thiết), nhận các lớp con được trả về từ hàm _subclass_container
vào biến subclasses
.
Gán các lớp con được lưu trữ trong subclasses
biến cho các thuộc tính của lớp cấp cao hơn.
Một số mẹo để làm cho các tình huống dễ dàng hơn:
Làm cho mã để gán các lớp con cho lớp cấp cao hơn dễ sao chép hơn và được sử dụng trong các lớp dẫn xuất từ lớp cấp cao hơn đã thay đổi chức năng của chúng __init__
:
Chèn trước dòng 12 trong mã chính:
def _subclass_init(self):
Sau đó chèn vào dòng chức năng này 5-6 (của mã chính) và thay thế dòng 4-7 bằng mã sau:
self._subclass_init(self)
Việc gán lớp con cho lớp cấp cao hơn có thể thực hiện được khi có nhiều / số lượng chưa biết của lớp con.
Thay thế dòng 6 bằng mã sau:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
Kịch bản ví dụ về nơi giải pháp này sẽ hữu ích và nơi không thể lấy tên lớp cấp cao hơn:
Một lớp, có tên "a" ( class a:
) được tạo. Nó có các lớp con cần truy cập nó (lớp cha). Một lớp con được gọi là "x1". Trong lớp con này, mã a.run_func()
được chạy.
Sau đó, một lớp khác, tên là "b" được tạo ra, có nguồn gốc từ lớp "a" ( class b(a):
). Sau đó, một số mã chạy b.x1()
(gọi hàm con "x1" của b, một lớp con dẫn xuất). Hàm này chạy a.run_func()
, gọi hàm "run_func" của lớp "a", không phải hàm "run_func" của lớp cha của nó, "b" (nếu cần), bởi vì hàm được định nghĩa trong lớp "a" được đặt để tham chiếu cho chức năng của lớp "a", vì đó là lớp cha của nó.
Điều này sẽ gây ra sự cố (ví dụ: nếu hàm a.run_func
đã bị xóa) và giải pháp duy nhất mà không cần viết lại mã trong lớp a.x1
sẽ là xác định lại lớp con x1
với mã cập nhật cho tất cả các lớp có nguồn gốc từ lớp "a" rõ ràng sẽ khó và không có giá trị nó.