PEP 443 - multiple types registered
I was reading the recently accepted PEP 443 and this is one of the examples: @fun.register(float) @fun.register(Decimal) def fun_num(arg, verbose=False): if verbose: print("Half of your number:", end=" ") print(arg / 2) Wouldn't a tuple of types be more suitable? I mean, programatically you will not apply the decorators from a list, but define the function and then write a loop: for t in some_types: fun.register(t, fun_num) which is less pleasant for the eyes. I would rather do: @fun.register((float, Decimal)) def fun_num(arg, verbose=False): ... This makes a lot of sense when you think that Python functions and constructs dealing with types usually also deal with tuples of types. E.g: isinstance(foo, (Bar, Baz)) except (Foo, Bar) as baz: Last thought: People are used with decorators returning a decorated function. This is not the case here... For some, it may be confusing at first. João Bernardo
On 6 cze 2013, at 01:47, João Bernardo
I was reading the recently accepted PEP 443 and this is one of the examples:
@fun.register(float) @fun.register(Decimal) def fun_num(arg, verbose=False): if verbose: print("Half of your number:", end=" ") print(arg / 2)
Wouldn't a tuple of types be more suitable?
There is barely any gain from supporting a tuple syntax, whereas it closes up ways of extending the API in the future or introducing new ways of dispatch with an analogous API. We left it out consciously.
Last thought: People are used with decorators returning a decorated function. This is not the case here... For some, it may be confusing at first.
fun.register() does return the decorated function. This is why the example above works. @singledispatch returns a compatible wrapper, which is analogous to what @lru_cache and countless other decorators do. Is there something I am missing here? Thanks for your feedback! -- Best regards, Łukasz Langa WWW: http://lukasz.langa.pl/ Twitter: @llanga IRC: ambv on #python-dev
fun.register() does return the decorated function. This is why the example above works. @singledispatch returns a compatible wrapper, which is analogous to what @lru_cache and countless other decorators do. Is there something I am missing here? Thanks for your feedback!
Copied from the PEP text: The register() attribute returns the *undecorated *function. This enables decorator stacking, pickling, as well as creating unit tests for each variant independently: It's not big deal, just not common
On 06/05/2013 05:05 PM, João Bernardo wrote:
fun.register() does return the decorated function. This is why the example above works. @singledispatch returns a compatible wrapper, which is analogous to what @lru_cache and countless other decorators do. Is there something I am missing here?
Copied from the PEP text:
The register() attribute returns the *undecorated *function. This enables decorator stacking, pickling, as well as creating unit tests for each variant independently:
The function is undecorated because it is simply a registration mechanism. The function does not need to be altered for this to work. -- ~Ethan~
On Wed, Jun 5, 2013 at 5:05 PM, João Bernardo
Copied from the PEP text:
The register() attribute returns the *undecorated *function. This enables decorator stacking, pickling, as well as creating unit tests for each variant independently:
The decorator doesn't change the function so there is no decorated version of the function to return. It just registers it in a dispatch table that the generic function uses. I think this is a fairly common pattern. For example, see flask.route. --- Bruce Latest blog post: Alice's Puzzle Page http://www.vroospeak.com Learn how hackers think: http://j.mp/gruyere-security
The decorator doesn't change the function so there is no decorated version of the function to return. It just registers it in a dispatch table that the generic function uses. I think this is a fairly common pattern. For example, see flask.route.
I've wrote all kind of decorators, including some that just store some information and returns the original function. This is not very important... The fact is that I still feel that register could allow a tuple of types without compromising the API. Maybe a "register_many" could be added then...
On Jun 6, 10:28 am, João Bernardo
The fact is that I still feel that register could allow a tuple of types without compromising the API. Maybe a "register_many" could be added then...
Isn't it simple enough to do yourself? def register_many(types): def _register_many(fn): for t in types: fun.register(type)(fn) return fn return _register_many
On 6 Jun 2013 10:29, "João Bernardo"
The decorator doesn't change the function so there is no decorated
version of the function to return. It just registers it in a dispatch table that the generic function uses. I think this is a fairly common pattern. For example, see flask.route.
I've wrote all kind of decorators, including some that just store some
information and returns the original function. This is not very important...
The fact is that I still feel that register could allow a tuple of types
without compromising the API. It's ambiguous relative to multiple dispatch APIs.
Maybe a "register_many" could be added then...
Anyone that is regularly registering multiple types for the same implementations would be well advised to start defining some appropriate ABCs and register those instead. Cheers, Nick.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
participants (6)
-
alex23
-
Bruce Leban
-
Ethan Furman
-
João Bernardo
-
Nick Coghlan
-
Łukasz Langa