George Trojan - NOAA Federal wrote: > Here is my test program: > > ''' generic test ''' > > import functools > import inspect > > def f(): > '''I am f''' > pass > > g = functools.partial(f) > g.__doc__ = '''I am g''' > g.__name__ = 'g' > > def partial(func, *args, **keywords): > def newfunc(*fargs, **fkeywords): > newkeywords = keywords.copy() > newkeywords.update(fkeywords) > return func(*(args + fargs), **newkeywords) > newfunc.func = func > newfunc.args = args > newfunc.keywords = keywords > return newfunc > > h = partial(f) > functools.update_wrapper(h, f) > h.__doc__ = '''I am h''' > h.__name__ = 'h' > > print(type(g), g.__name__, inspect.getdoc(g)) > print(type(h), h.__name__, inspect.getdoc(h)) > help(g) > help(h) > > The output is what I expect: > > (devenv-3.5.1) dilbert@gtrojan> python x.py > <class 'functools.partial'> g I am g > <class 'function'> h I am h > > However the help screens for h and g are different. help(h) is again what > I expect: > > Help on function h in module __main__: > > h() > I am h > > But help(g) is (almost) identical to help(functools.partial), the doc > string disappears: > > Help on partial object: > > g = class partial(builtins.object) > | partial(func, *args, **keywords) - new function with partial > | application of the given arguments and keywords. > ... > > The module functools has partial() defined as above, then overrides the > definition by importing partial from _functools. That would explain the > above behaviour. My question is why?
This is not specific to functools.partial. partial(some_func, ...) creates an instance of the partial class. Unfortunately the instance.__doc__ is generally ignored in favour of class.__doc__: >>> class Foo: ... "CLASS" ... >>> foo = Foo() >>> foo.__doc__ = "INSTANCE" >>> help(foo) Help on Foo in module __main__ object: class Foo(builtins.object) | CLASS [...] Being looked up in the class is standard behaviour for __dunder__ attributes: >>> class A: ... def __len__(self): return 42 ... >>> a = A() >>> a.__len__ = lambda: 123 >>> a.__len__() 123 >>> len(a) 42 Most of the time it saves at least a dict lookup, but sometimes it bites you. -- https://mail.python.org/mailman/listinfo/python-list