On Wed, May 06, 2020 at 09:17:15PM -0400, Eric V. Smith wrote: > I think David is right: itertools.chain.from_iterable() is the only > place I know of with an attribute on a function that's another function.
Functions decorated with `functools.wrap` have an attribute that gives the original function: py> def f(): return True ... py> g = wraps(f)(lambda: False) py> g() False py> g.__wrapped__() True Likewise `functools.partial` objects have a `func` attribute that gives the original function: py> h = partial(lambda a, b: a + b) py> h = partial(lambda a, b: a + b, 1000) py> h(1) 1001 py> h.func(1, 2) 3 Functions which have been decorated with lru_cache are given two function attributes, `cache_clear` and `cache_info`. I believe that there is also an example in mock, but I don't remember the details. I wanted to use this attributes on the median() function in the statistics module to spell the less-important variations: median() # standard version as taught in schools with the specialist versions as attributes: median.lower() median.upper() but I was talked out of it in favour of three separate functions: median, median_lower, median_upper I still regret giving in on this point. IMO the lower and upper medians are useful but not important enough to be top-level functions. "Namespaces are one honking great idea -- let's do more of those!" Functions are namespaces! They have internal `__dicts__` and can hold arbitrary attributes. Why are we so reluctant to follow the Zen and use those namespaces? > Alternate constructors are generally classmethods. The fact that chain.from_iterable is, in a sense, an alternative constructor is an implementation detail. `chain` happens to be a class that returns an instance of `chain`, but it could have simply returned a generic generator, or some other kind of instance. > And it's the documentation that I'm concerned about: I don't think > itertools.chain.from_iterable() is very discoverable. Plenty of people > don't know it exists. That's my concern with this approach. It isn't hard to add a "See also..." line to the chain docstring pointing to the existence of chain.from_iterable, and we should do that. Also, help() should be enhanced to give better support for function attributes. Your point about discoverability is taken, but it is no less discoverable than other namespaces. If I know a package: import package package.function(arg) that knowledge doesn't give me any insight into any subpackages that I haven't imported and may not even know about: # How do I learn to do this? from package.subpackage import anotherfunction -- Steven _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/QTDBXD733BL2AFYG7V6IPAJ5BG7T42VF/ Code of Conduct: http://python.org/psf/codeofconduct/