2012-06-24 12 views
24

subclass của một Python dict tác phẩm như mong đợi:Làm thế nào để phân lớp một OrderedDict?

>>> class DictSub(dict): 
...  def __init__(self): 
...   self[1] = 10 
...   
>>> DictSub() 
{1: 10} 

Tuy nhiên, làm điều tương tự với một collections.OrderedDict không hoạt động:

>>> import collections 
>>> class OrdDictSub(collections.OrderedDict): 
...  def __init__(self): 
...   self[1] = 10 
...   
>>> OrdDictSub() 
(…) 
AttributeError: 'OrdDictSub' object has no attribute '_OrderedDict__root' 

Như vậy, việc thực hiện OrderedDict sử dụng một __root atribute tư nhân, trong đó ngăn chặn lớp con OrdDictSub hoạt động như lớp con DictSub. Tại sao? Làm thế nào người ta có thể kế thừa từ một OrderedDict?

+2

Tại sao bạn nên downvote? – EOL

Trả lời

33

Bạn cần phải gọi OrderedDict.__init__ từ __init__ của bạn:

class OrdDictSub(collections.OrderedDict): 
    def __init__(self): 
     super(OrdDictSub, self).__init__() 

Bạn đã không cho OrderedDict một cơ hội để khởi tạo riêng của mình. Về mặt kỹ thuật, bạn cũng muốn làm điều này cho lớp con dict của bạn, vì bạn muốn có một số dict được khởi tạo đầy đủ. Thực tế là dict hoạt động mà không có nó chỉ là may mắn.

+0

Cảm ơn. Thật tệ của tôi. Đúng là tôi bị ảnh hưởng bởi dict. Tôi thậm chí còn hỏi một câu hỏi về dict một số thời gian trước đây (http://stackoverflow.com/questions/2033150/subclassing-dict-should-dict-init-be-called)! – EOL

+6

bạn không muốn args và kwargs trong init? 'def __init __ (self, * args, ** kwargs): super (OrdDictSub, self) .__ init __ (* args, ** kwargs)' – hobs

2

Cố gắng khởi tạo lớp cha trong phương pháp __init__:

def __init__(self): 
    collections.OrderedDict.__init__(self) 
    self[1] = 10 

Đây là cách thông thường để khởi tạo một lớp con. Bạn không để gọi phương thức của lớp cha __init__ nói chung, nhưng nếu bạn không có kiến ​​thức về thực hiện của lớp cha bạn thực sự nên gọi __init__.

+1

Sử dụng 'super()' để gọi các phương thức của siêu lớp – astynax

+1

@astynax: Cả hai cách đều hoạt động, vì vậy đó là vấn đề về phong cách. –

+9

@DietrichEpp: Câu trả lời hay, nhưng việc sử dụng 'super()' không phải là vấn đề về phong cách: điều quan trọng là sử dụng nó (thay vì sử dụng một siêu lớp rõ ràng) trong trường hợp lớp của bạn được phân lớp. Ví dụ tham khảo: http://rhettinger.wordpress.com/2011/05/26/super-considered-super/. Hơn nữa, việc sử dụng 'super()' làm cho mã dễ dàng hơn để duy trì (dễ dàng hơn để thay đổi tên của lớp). – EOL