Reputation: 3
Let's assume I define a simple 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.
I see that object __doc__
is picked up by ?
in 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
but ignored by 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)
Is it possible to influence help
behavior without modifying Class docstring
? I would like to Class docstring
to be ignored when working with instances.
Upvotes: 0
Views: 859
Reputation: 160597
Forcing the help
function requires changes to its implementation from what I've understood. It is much easier to create a little helper function that temporarily re-assigns __doc__
on the class:
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)
This yields the, from what I've understood, wanted effect of having the docstring of the instance replace that of the 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 ..
I don't really like this, though, and also know that you must perform a try-except
in there for classes that don't allow you to set attributes on them like that. In short, doable but clunky.
Upvotes: 1
Reputation: 152745
First: I wouldn't recommend it! If you seriously change the logic depending on the arguments, you are probably better of using a factory function and several distinct (sub-)classes.
After having said that: it's possible. One way would be using dynamic types and subclassing. However you need to use __new__
instead of __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)
Upvotes: 1