Make functools.singledispatch register method return original function.
Right now, an example for single dispatch would be: from functools import singledispatch @singledispatch def fun(arg, verbose=True): if verbose: print("Let me just say,", end=" ") print(arg) @fun.register(int) def _(arg, verbose=True): if verbose: print("Strength in numbers, eh?", end=" ") print(arg) @fun.register(list) def _(arg, verbose=True): if verbose: print("Enumerate this:") for i, elem in enumerate(arg): print(i, elem) But this makes a useless _ function, that should either be deleted or ignored. For properties, a common pattern is this: class Foo: @property def bar(self): return self._bar @bar.setter def bar(self, value): self._bar = value So I'm suggesting that @function.register for single dispatch functions returns the same function, so you would end up with something like: @singledispatch def fun(arg, verbose=True): if verbose: print("Let me just say,", end=" ") print(arg) @fun.register(int) def fun(arg, verbose=True): if verbose: print("Strength in numbers, eh?", end=" ") print(arg) And to get back the old behaviour, where you can get the function being decorated, just call it afterwards: @singledispatch def fun(arg, verbose=True): if verbose: print("Let me just say,", end=" ") print(arg) def used_elsewhere(arg, verbose=True): if verbose: print("Strength in numbers, eh?", end=" ") print(arg) fun.register(int)(used_elsewhere) But this goes against what a single-dispatch function is, so I think this is a minor enough use case to not worry about.
On 17/06/17 23:27, Mital Ashok via Python-ideas wrote:
[snip] So I'm suggesting that @function.register for single dispatch functions returns the same function, so you would end up with something like:
@singledispatch def fun(arg, verbose=True): if verbose: print("Let me just say,", end=" ") print(arg)
@fun.register(int) def fun(arg, verbose=True): if verbose: print("Strength in numbers, eh?", end=" ") print(arg) In principle, I like it! However...
And to get back the old behaviour, where you can get the function being decorated, just call it afterwards:
A backwards incompatible change like this is not going to happen. In actual fact, a couple of uses of the current behaviour are in the docs at https://docs.python.org/3/library/functools.html#functools.singledispatch :
The register() attribute returns the undecorated function which enables decorator stacking, pickling, as well as creating unit tests for each variant independently:
@fun.register(float)
... @fun.register(Decimal) ... def fun_num(arg, verbose=False): ... if verbose: ... print("Half of your number:", end=" ") ... print(arg / 2) ...
fun_num is fun False
Perhaps it makes sense to add a new method to singledispatch that has the behaviour you're suggesting, just with a different name? -- Thomas
On 18 June 2017 at 07:27, Mital Ashok via Python-ideas
Right now, an example for single dispatch would be:
from functools import singledispatch
@singledispatch def fun(arg, verbose=True): if verbose: print("Let me just say,", end=" ") print(arg)
@fun.register(int) def _(arg, verbose=True): if verbose: print("Strength in numbers, eh?", end=" ") print(arg)
@fun.register(list) def _(arg, verbose=True): if verbose: print("Enumerate this:") for i, elem in enumerate(arg): print(i, elem)
But this makes a useless _ function, that should either be deleted or ignored.
Don't do that, give the overloads meaningful names that your test suite can then use to check that they do the right thing independently of the dispatch process. Even if you're not doing unit testing at that level, the names will also show up in exception tracebacks and other forms of introspection (e.g. process state dumps), and seeing descriptive names like "_fun_for_int" and "_fun_for_list" is *significantly* more informative than seeing multiple distinct functions all called "_" or "__". Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
participants (3)
-
Mital Ashok
-
Nick Coghlan
-
Thomas Jollans