Dưới đây là một câu hỏi gấp đôi, với một phần lý thuyết và thực tiễn một:Phân lớp dict: nên dict .__ init __() được gọi?
Khi subclassing dict:
class ImageDB(dict):
def __init__(self, directory):
dict.__init__(self) # Necessary??
...
nên dict.__init__(self)
được gọi là, cũng giống như một "an toàn" đo (ví dụ, trong trường hợp có một số chi tiết triển khai không quan trọng nào quan trọng)? có nguy cơ mã ngắt với phiên bản Python trong tương lai không nếu dict.__init__()
là không phải là được gọi là? Tôi đang tìm kiếm một lý do cơ bản để làm một việc này hay thứ khác, ở đây (thực tế, gọi dict.__init__()
là an toàn).
Tôi đoán là khi ImageDB.__init__(self, directory)
được gọi, tự đã là một đối tượng dict trống mới, và do đó không cần gọi dict.__init__
(tôi muốn lệnh dict trống, lúc đầu). Điều này có đúng không?
Sửa:
Câu hỏi thực tế hơn đằng sau những câu hỏi cơ bản ở trên là như sau. Tôi đã nghĩ về subclassing dict bởi vì tôi sẽ sử dụng cú pháp db […] khá thường xuyên (thay vì làm db.contents […] mọi lúc); dữ liệu duy nhất của đối tượng (thuộc tính) thực sự là một dict. Tôi muốn thêm một vài phương thức vào cơ sở dữ liệu (chẳng hạn như get_image_by_name()
, hoặc get_image_by_code()
, ví dụ) và chỉ ghi đè __init__()
, bởi vì cơ sở dữ liệu hình ảnh được xác định bởi thư mục chứa nó.
Nói tóm lại thì (thực tế) câu hỏi có thể là: là những gì thực hiện tốt cái gì đó hoạt động như một cuốn từ điển, ngoại trừ việc khởi tạo của nó là khác nhau (nó chỉ mất một tên thư mục), và rằng nó có thêm phương pháp?
"Nhà máy" được đề cập trong nhiều câu trả lời. Vì vậy, tôi đoán nó tất cả các boils xuống: làm bạn phân lớp dict, ghi đè lên __init__()
và thêm phương pháp, hoặc bạn viết một (nhà máy) chức năng trả về một dict, mà bạn thêm phương pháp? Tôi có khuynh hướng thích giải pháp đầu tiên, bởi vì hàm factory trả về một đối tượng có kiểu không chỉ ra rằng nó có các ngữ nghĩa và phương thức bổ sung, nhưng bạn nghĩ gì?
Chỉnh sửa 2:
tôi thu thập từ các câu trả lời mọi người rằng nó không phải là một ý tưởng tốt để phân lớp dict khi lớp mới "không phải là một cuốn từ điển", và đặc biệt khi phương pháp __init__
của nó không thể đi cùng đối số là __init__
của dict (đây là trường hợp trong "câu hỏi thực tế" ở trên). Nói cách khác, nếu tôi hiểu đúng, sự đồng thuận dường như là: khi bạn phân lớp, tất cả các phương thức (bao gồm khởi tạo) phải có chữ ký giống như các phương thức lớp cơ sở. Điều này cho phép isinstance (subclass_instance, dict) đảm bảo rằng subclass_instance.__init__()
có thể được sử dụng như dict.__init__()
, ví dụ.
Một câu hỏi thực tế khác sau đó bật lên: làm thế nào một lớp học giống như dict, ngoại trừ phương pháp khởi tạo của nó, được thực hiện? mà không có phân lớp? điều này sẽ yêu cầu một số mã boilerplate khó chịu, không?
Chức năng của nhà máy là cách thực hiện. Nếu bạn cần tùy chỉnh hành vi * instance *, thì bạn có thể muốn tạo một lớp con. Nếu bạn chỉ muốn ghi đè * khởi tạo *, bạn không cần phải phân lớp bất kỳ thứ gì, vì các cá thể của bạn không khác với các cá thể chuẩn. Hãy nhớ rằng __init__ không được coi là một phần của giao diện của cá thể, mà là của lớp. –
Theo như tôi thấy nó cho vấn đề này nó sẽ là tốt nhất để thêm phương pháp '__getitem__' vào ImageDB của bạn thay vì subclassing một dict, bởi vì nó là _not_ một dict. Điều này cho phép bạn làm những gì bạn muốn, _without_ có tất cả các phương thức như 'pop()' có vẻ không phù hợp với lớp của bạn. –
@gs: Tốt, về pop; nó thực sự, ít nhất là cho thời điểm này, không liên quan (nội dung cơ sở dữ liệu được xác định khi khởi tạo chỉ). Tôi nghĩ rằng nó thực sự là tốt nhất mà việc thực hiện chặt chẽ phù hợp với các tính năng cần thiết. – EOL