如何强制帮助使用覆盖 __doc__

How to force help to use overridden __doc__

假设我定义了一个简单的 class Foo:

class Foo(object):
    """This is Foo"""
    def __init__(self, label):
        self.__doc__ = "This is {} Foo".format(label)

    def __call(self, *args):
        ... # Some behavior which depends on the constructor arguments.

我看到对象 __doc__? 在 IPython 中拾取:

In [1]: %doctest_mode
Exception reporting mode: Plain
Doctest mode is: ON
>>> some = Foo("some")
>>> ?some
Type:            Foo
String form:     <__main__.Foo object at 0x7f01620a49b0>
Docstring:       This is some Foo
Class docstring: This is Foo

但被 help 忽略:

>>> help(some)

Help on Foo in module __main__ object:

class Foo(builtins.object)
 |  This is Foo
 |  
 |  Methods defined here:
 |  
 |  __init__(self, label)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
(END)

是否可以在不修改 Class docstring 的情况下影响 help 行为?我希望 Class docstring 在处理实例时被忽略。

强制执行 help 函数需要根据我的理解更改其实现。创建一个临时在 class 上重新分配 __doc__ 的小辅助函数要容易得多:

def my_help(obj):
    if not isinstance(obj, type):  # instances
        old_doc, type(obj).__doc__ = type(obj).__doc__, obj.__doc__
        help(type(obj))
        type(obj).__doc__ = old_doc
    else:
        help(obj)

根据我的理解,这产生了用实例的文档字符串替换 class:

的预期效果
my_help(Foo('foo'))
Help on class Foo in module __main__:

class Foo(builtins.object)
 |  This is foo Foo
 |  
 |  Methods defined here:
 |  
 |  __init__(self, label)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 #  .. snipped ..

不过,我不太喜欢这样,并且还知道您必须在其中对 class 执行 try-except,因为它们不允许您像那样设置属性.简而言之,可行但笨拙。

首先:我不会推荐它!如果你根据参数认真地改变逻辑,你可能最好使用工厂函数和几个不同的 (sub-)类.

话说回来:这是可能的。一种方法是使用动态类型和子类化。但是你需要使用 __new__ 而不是 __init__:

class Foo(object):
    """This is Foo"""
    def __new__(cls, label):
        newcls = type('FooSubclass', (Foo, ), {'__doc__': "This is {} Foo".format(label)})
        return newcls

>>> help(Foo('a'))
Help on class FooSubclass in module __main__:

class FooSubclass(Foo)
 |  This is a Foo
 |  
 |  Method resolution order:
 |      FooSubclass
 |      Foo
 |      __builtin__.object
 |  
 |  Static methods inherited from Foo:
 |  
 |  __new__(cls, label)
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from Foo:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)