2010-01-08 3 views
70

Tôi đang cố gắng thực hiện một số thừa kế lớp bằng Python. Tôi muốn mỗi lớp và lớp kế thừa có những tài liệu tốt. Vì vậy, tôi nghĩ cho lớp kế thừa, tôi muốn nó:Thừa kế tài liệu trong kế thừa lớp Python

  • kế thừa các lớp cơ sở docstring
  • có thể thêm tài liệu hướng dẫn thêm liên quan đến docstring

Có bất kỳ (có thể thanh lịch hoặc pythonic) cách thực hiện loại thao tác docstring này trong tình huống thừa kế lớp? Làm thế nào về nhiều thừa kế?

Trả lời

32

Bạn không phải là người duy nhất! Đã có một cuộc thảo luận về comp.lang.python về điều này một thời gian trước đây và một công thức đã được tạo. Kiểm tra xem nó ra here.

""" 
doc_inherit decorator 

Usage: 

class Foo(object): 
    def foo(self): 
     "Frobber" 
     pass 

class Bar(Foo): 
    @doc_inherit 
    def foo(self): 
     pass 

Now, Bar.foo.__doc__ == Bar().foo.__doc__ == Foo.foo.__doc__ == "Frobber" 
""" 

from functools import wraps 

class DocInherit(object): 
    """ 
    Docstring inheriting method descriptor 

    The class itself is also used as a decorator 
    """ 

    def __init__(self, mthd): 
     self.mthd = mthd 
     self.name = mthd.__name__ 

    def __get__(self, obj, cls): 
     if obj: 
      return self.get_with_inst(obj, cls) 
     else: 
      return self.get_no_inst(cls) 

    def get_with_inst(self, obj, cls): 

     overridden = getattr(super(cls, obj), self.name, None) 

     @wraps(self.mthd, assigned=('__name__','__module__')) 
     def f(*args, **kwargs): 
      return self.mthd(obj, *args, **kwargs) 

     return self.use_parent_doc(f, overridden) 

    def get_no_inst(self, cls): 

     for parent in cls.__mro__[1:]: 
      overridden = getattr(parent, self.name, None) 
      if overridden: break 

     @wraps(self.mthd, assigned=('__name__','__module__')) 
     def f(*args, **kwargs): 
      return self.mthd(*args, **kwargs) 

     return self.use_parent_doc(f, overridden) 

    def use_parent_doc(self, func, source): 
     if source is None: 
      raise NameError, ("Can't find '%s' in parents"%self.name) 
     func.__doc__ = source.__doc__ 
     return func 

doc_inherit = DocInherit 
+0

Đó là gọn gàng để có phương pháp kế thừa chuỗi tài liệu của phương thức lớp cha. Điều đó sẽ hữu ích trong nhiều trường hợp tôi nghĩ. Tôi đã suy nghĩ nhiều hơn về docstring cho cả lớp, nơi tôi muốn kế thừa và nối thêm. –

+0

Ah, gotcha. Trong trường hợp đó, hầu hết các thế hệ doc đã làm điều đó cho bạn. –

23

Bạn có thể ghép các docstrings dễ dàng:

class Foo(object): 
    """ 
    Foo Class. 
    This class foos around. 
    """ 
    pass 

class Bar(Foo): 
    """ 
    Bar class, children of Foo 
    Use this when you want to Bar around. 
    parent: 
    """ 
    __doc__ += Foo.__doc__ 
    pass 

Tuy nhiên, đó là vô ích. Hầu hết các công cụ tạo tài liệu (SphinxEpydoc được bao gồm) sẽ đã kéo chuỗi tài liệu gốc, bao gồm cả cho các phương thức. Vì vậy, bạn không phải làm bất cứ điều gì.

+9

Thật vậy, hầu hết các công cụ tài liệu đều làm điều đó. Nhưng hàm help() được xây dựng sẵn thì không. – MarioVilas

+0

@MarioVilas: có lẽ đó là lỗi cần được báo cáo? – naught101

3

Không đặc biệt là thanh lịch, nhưng đơn giản và trực tiếp:

class X(object): 
    """This class has a method foo().""" 
    def foo(): pass 

class Y(X): 
    __doc__ = X.__doc__ + ' Also bar().' 
    def bar(): pass 

Bây giờ là:

>>> print Y.__doc__ 
This class has a method foo(). Also bar(). 
+0

Nếu bạn muốn thực hiện điều này cho 'Init docstring', có cách nào để thực hiện nó trong định nghĩa' Y' không? Cách duy nhất tôi có thể làm là sử dụng '__init __.__ doc__ = X .__ init __.__ doc__ +" Ngoài ra một tham số khác "' theo định nghĩa '__init__' trong' Y' nhưng điều này dường như gây rối với định dạng, gây thêm thêm không gian. – mgilbert

2

Một stile hỗn hợp mà có thể duy trì cả hai cú pháp docstring kế thừa và thứ tự ưu tiên có thể là:

class X(object): 
    """This class has a method foo().""" 
    def foo(): pass 

class Y(X): 
    """ Also bar().""" 
    __doc__ = X.__doc__ + __doc__ 
    def bar(): pass 

Với cùng một đầu ra như của Alex:

>>> print Y.__doc__ 
This class has a method foo(). Also bar(). 

băng mỏng: chơi với docstring có thể làm cho mô-đun của bạn không sử dụng được với python -OO, mong đợi một số:

TypeError: cannot concatenate 'str' and 'NoneType' objects 
-1

tôi đã viết custom_inherit cung cấp một số công cụ trọng lượng nhẹ đơn giản để xử lý docstring thừa kế.

Nó cũng đi kèm với một số kiểu mặc định đẹp để hợp nhất các loại tài liệu khác nhau (ví dụ: Numpy, Google và các quy tắc được định dạng lại). Bạn cũng có thể cung cấp phong cách của riêng bạn rất dễ dàng.

Đoạn mã hóa chồng chéo sẽ trì hoãn phần của trẻ, nếu không chúng sẽ được hợp nhất cùng với định dạng đẹp.