Những gì tôi đang nói ở đây là các lớp học lồng nhau. Về cơ bản, tôi có hai lớp mà tôi đang làm người mẫu. Một lớp tải xuống và lớp tải xuống. Khái niệm OOP rõ ràng ở đây là sáng tác. Tuy nhiên, thành phần không nhất thiết có nghĩa là làm tổ, phải không?
Tôi có mã trông giống như thế này:
class DownloadThread:
def foo[self]:
pass
class DownloadManager[]:
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadThread[]]
Nhưng bây giờ tôi đang tự hỏi liệu có tình huống làm tổ sẽ tốt hơn không. Cái gì đó như:
class DownloadManager[]:
class DownloadThread:
def foo[self]:
pass
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadManager.DownloadThread[]]
0
Bạn có thể muốn làm điều này khi lớp "bên trong" là một lần, sẽ không bao giờ được sử dụng bên ngoài định nghĩa của lớp bên ngoài. Ví dụ: sử dụng một metaclass, đôi khi nó tiện dụng để làm
class Foo[object]:
class __metaclass__[type]:
....
Thay vì xác định một metaclass một cách riêng biệt, nếu bạn chỉ sử dụng nó một lần.
Lần duy nhất khác tôi đã sử dụng các lớp lồng nhau như vậy, tôi chỉ sử dụng lớp bên ngoài làm không gian tên để nhóm một loạt các lớp liên quan chặt chẽ với nhau:
class Group[object]:
class cls1[object]:
...
class cls2[object]:
...
Sau đó, từ một mô -đun khác, bạn có thể nhập nhóm và gọi chúng là nhóm.CLS1, Group.CLS2, v.v. Tuy nhiên, người ta có thể lập luận rằng bạn có thể hoàn thành chính xác giống nhau [có lẽ theo cách ít khó hiểu hơn] bằng cách sử dụng mô -đun.
Đã trả lời ngày 17 tháng 9 năm 2008 lúc 1:12Sep 17, 2008 at 1:12
3
Tôi không biết Python, nhưng câu hỏi của bạn có vẻ rất chung chung. Bỏ qua tôi nếu nó cụ thể với Python.
Lớp học là tất cả về phạm vi. Nếu bạn nghĩ rằng một lớp sẽ chỉ có ý nghĩa trong bối cảnh của một người khác, thì trước đây có lẽ là một ứng cử viên tốt để trở thành một lớp lồng nhau.
Nó là một mô hình phổ biến làm cho các lớp trợ giúp như các lớp riêng tư, lồng nhau.
Đã trả lời ngày 17 tháng 9 năm 2008 lúc 1:14Sep 17, 2008 at 1:14
André Chalellaandré ChalellaAndré Chalella
13.4K10 Huy hiệu vàng53 Huy hiệu bạc61 Huy hiệu Đồng10 gold badges53 silver badges61 bronze badges
1
Có một cách sử dụng khác cho lớp lồng nhau, khi người ta muốn xây dựng các lớp kế thừa có chức năng nâng cao được gói gọn trong một lớp lồng nhau cụ thể.
Xem ví dụ này:
class foo:
class bar:
... # functionalities of a specific sub-feature of foo
def __init__[self]:
self.a = self.bar[]
...
... # other features of foo
class foo2[foo]:
class bar[foo.bar]:
... # enhanced functionalities for this specific feature
def __init__[self]:
foo.__init__[self]
Lưu ý rằng trong hàm tạo của foo
, dòng self.a = self.bar[]
sẽ xây dựng một
class DownloadManager[]:
class DownloadThread:
def foo[self]:
pass
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadManager.DownloadThread[]]
0 khi đối tượng được xây dựng thực sự là một đối tượng foo
và đối tượng class DownloadManager[]:
class DownloadThread:
def foo[self]:
pass
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadManager.DownloadThread[]]
2 khi đối tượng được xây dựng thực sự là một đối tượng class DownloadManager[]:
class DownloadThread:
def foo[self]:
pass
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadManager.DownloadThread[]]
3.Nếu lớp
class DownloadManager[]:
class DownloadThread:
def foo[self]:
pass
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadManager.DownloadThread[]]
4 được xác định bên ngoài lớp foo
, cũng như phiên bản di truyền của nó [ví dụ sẽ được gọi là class DownloadManager[]:
class DownloadThread:
def foo[self]:
pass
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadManager.DownloadThread[]]
6], thì việc xác định lớp mới class DownloadManager[]:
class DownloadThread:
def foo[self]:
pass
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadManager.DownloadThread[]]
3 sẽ đau hơn nhiều Dòng đầu tiên được thay thế bằng class DownloadManager[]:
class DownloadThread:
def foo[self]:
pass
def __init__[self]:
dwld_threads = []
def create_new_thread[]:
dwld_threads.append[DownloadManager.DownloadThread[]]
9, ngụ ý viết lại toàn bộ hàm tạo.1
Bạn có thể sử dụng một lớp làm trình tạo lớp. Thích [trong một số mã Cuff :]
class gen[object]:
class base_1[object]: pass
...
class base_n[object]: pass
def __init__[self, ...]:
...
def mk_cls[self, ..., type]:
'''makes a class based on the type passed in, the current state of
the class, and the other inputs to the method'''
Tôi cảm thấy như khi bạn cần chức năng này, nó sẽ rất rõ ràng với bạn. Nếu bạn không cần phải làm điều gì đó tương tự hơn thì có lẽ nó không phải là trường hợp sử dụng tốt.
Tim Cooper
155K37 Huy hiệu vàng322 Huy hiệu bạc275 Huy hiệu Đồng37 gold badges322 silver badges275 bronze badges
Đã trả lời ngày 17 tháng 9 năm 2008 lúc 1:34Sep 17, 2008 at 1:34
tim.tadhtim.tadhtim.tadh
8696 Huy hiệu bạc16 Huy hiệu Đồng6 silver badges16 bronze badges
Thực sự không có lợi ích gì khi làm điều này, ngoại trừ nếu bạn đang đối phó với các metaclass.
Lớp học: Bộ thực sự không phải là những gì bạn nghĩ nó là. Đó là một phạm vi kỳ lạ, và nó làm những điều kỳ lạ. Nó thực sự thậm chí không tạo ra một lớp học! Nó chỉ là một cách để thu thập một số biến - tên của lớp, các cơ sở, một chút từ điển của các thuộc tính và một metaclass.
Tên, từ điển và các cơ sở đều được chuyển đến hàm là metaclass, và sau đó nó được gán cho biến 'tên' trong phạm vi mà lớp: bộ: bộ.
Những gì bạn có thể đạt được bằng cách gây rối với các metaclass, và thực sự bằng các lớp học làm tổ trong các lớp tiêu chuẩn chứng khoán của bạn, khó đọc mã hơn, khó hiểu hơn về mã và các lỗi kỳ quặc khó hiểu mà không quen thuộc với lý do tại sao 'lớp' ' Phạm vi hoàn toàn khác với bất kỳ phạm vi Python nào khác.
Đã trả lời ngày 17 tháng 9 năm 2008 lúc 1:52Sep 17, 2008 at 1:52
JerubjerubJerub
40,9K15 Huy hiệu vàng72 Huy hiệu bạc90 Huy hiệu đồng15 gold badges72 silver badges90 bronze badges
2
Một trường hợp sử dụng tốt cho tính năng này là xử lý lỗi/ngoại lệ, ví dụ:
class DownloadManager[object]:
class DowndloadException[Exception]:
pass
def download[self]:
...
Bây giờ người đang đọc mã đã biết tất cả các ngoại lệ có thể liên quan đến lớp này.
Dù bằng cách nào, được xác định bên trong hoặc bên ngoài một lớp, sẽ hoạt động. Dưới đây là chương trình Lịch trình trả lương của nhân viên trong đó lớp trợ giúp mà Empinit được nhúng bên trong nhân viên lớp:
class Employee:
def level[self, j]:
return j * 5E3
def __init__[self, name, deg, yrs]:
self.name = name
self.deg = deg
self.yrs = yrs
self.empInit = Employee.EmpInit[self.deg, self.level]
self.base = Employee.EmpInit[self.deg, self.level].pay
def pay[self]:
if self.deg in self.base:
return self.base[self.deg][] + self.level[self.yrs]
print[f"Degree {self.deg} is not in the database {self.base.keys[]}"]
return 0
class EmpInit:
def __init__[self, deg, level]:
self.level = level
self.j = deg
self.pay = {1: self.t1, 2: self.t2, 3: self.t3}
def t1[self]: return self.level[1*self.j]
def t2[self]: return self.level[2*self.j]
def t3[self]: return self.level[3*self.j]
if __name__ == '__main__':
for loop in range[10]:
lst = [item for item in input[f"Enter name, degree and years : "].split[' ']]
e1 = Employee[lst[0], int[lst[1]], int[lst[2]]]
print[f'Employee {e1.name} with degree {e1.deg} and years {e1.yrs} is making {e1.pay[]} dollars']
print["EmpInit deg {0}\nlevel {1}\npay[deg]: {2}".format[e1.empInit.j, e1.empInit.level, e1.base[e1.empInit.j]]]
Để xác định nó bên ngoài, chỉ cần empinit không suy nghĩ và thay đổi nhân viên. Tuy nhiên, vì nhân viên là bộ điều khiển của Empinit và người dùng không trực tiếp khởi tạo hoặc giao diện với nó, nên việc định nghĩa nó bên trong vì nó không phải là một lớp độc lập. Cũng lưu ý rằng Cấp độ Phương thức [] được thiết kế để được gọi trong cả hai lớp ở đây. Do đó, nó cũng có thể được định nghĩa thuận tiện là một phương pháp tĩnh trong nhân viên để chúng tôi không cần phải chuyển nó vào empinit, thay vào đó chỉ cần gọi nó với nhân viên.level [].