Issue42812
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2021-01-03 05:51 by chaim422, last changed 2022-04-11 14:59 by admin.
Messages (12) | |||
---|---|---|---|
msg384255 - (view) | Author: Chaim Gewirtz (chaim422) | Date: 2021-01-03 05:51 | |
Why should @overload need to be followed by an implementation when an implementation already exists in the parent class? Illustrative example: class Parent: def foo(**kwargs): """Argument names of foo vary depending on the child class.""" class Child(Parent): @overload foo(a, b): ... Raises: "NotImplementedError: You should not call an overloaded function. A series of @overload-decorated functions outside a stub module should always be followed by an implementation that is not @overload-ed." |
|||
msg384265 - (view) | Author: Yurii Karabas (uriyyo) * | Date: 2021-01-03 11:53 | |
The purpose of `@overload` is quite different. I believe you thought that this is smth like `@override` in Java world but it different. Basically, the correct usage of `@overaload` is: ``` @overload def process(response: None) -> None: ... @overload def process(response: int) -> tuple[int, str]: ... @overload def process(response: bytes) -> str: ... def process(response): <actual implementation> ``` Please, follow this link for more information https://docs.python.org/3/library/typing.html#typing.overload |
|||
msg384283 - (view) | Author: Chaim Gewirtz (chaim422) | Date: 2021-01-03 16:33 | |
"The purpose of `@overload` is quite different." So, this would overload the @overload decorator. Hmmm... Is there a better way to accomplish this goal? What would you suggest, a new decorator? |
|||
msg384284 - (view) | Author: Chaim Gewirtz (chaim422) | Date: 2021-01-03 16:40 | |
To clarify, this is how it's being done now a dozen times in actual production code: class Child(Parent): @overload foo(a, b): ... def overload(**kwargs): return super().foo(**kwargs) The goal of this proposed enhancement is to remove two extra lines of code per Child class. |
|||
msg384285 - (view) | Author: Yurii Karabas (uriyyo) * | Date: 2021-01-03 17:18 | |
`mypy` will produce an error on such code: ``` class Parent: def foo(self, **kwargs): """Argument names of foo vary depending on the child class.""" class Child(Parent): @overload def foo(self, a, b): pass def foo(self, **kwargs): return super().foo(**kwargs) ``` Result ``` temp.py:10: error: Single overload definition, multiple required temp.py:10: error: Signature of "foo" incompatible with supertype "Parent" Found 2 errors in 1 file (checked 1 source file) ``` In case if you want to add an overload for method I would recommend to use such pattern: ``` class Parent: def foo(self, **kwargs): """Argument names of foo vary depending on the child class.""" class Child(Parent): @overload def foo(self, a, b): pass @overload def foo(self, **kwargs): pass def foo(self, **kwargs): return super().foo(**kwargs) ``` So signature of `foo` will still match to parent class signature, but it will also have an overloaded variant. |
|||
msg384286 - (view) | Author: Chaim Gewirtz (chaim422) | Date: 2021-01-03 17:25 | |
Interesting. PyCharm has no problem with this code. It also autocompletes the argument names for me, which is very useful, especially since there a dozen different Child classes. Isn't "Simple is better than complex", and doesn't "...practicality beat purity"? |
|||
msg384287 - (view) | Author: Yurii Karabas (uriyyo) * | Date: 2021-01-03 17:31 | |
I think the simplest solution in your case is not to use `@overload`, as far as I understand you want to override the signature of base method. This code won't produce any error when used with `mypy`: ``` class Parent: def foo(**kwargs): """Argument names of foo vary depending on the child class.""" class Child(Parent): def foo(self, a, b): pass `` |
|||
msg384288 - (view) | Author: Chaim Gewirtz (chaim422) | Date: 2021-01-03 17:43 | |
What is better? A. Keeping Python as is, with four separate signature declarations (1x Parent, 2x @overload Child, and 1x actual signature in Child), and a second method call overhead at runtime (to satisfy mypy as it exists now). --or-- B. Simplify Python to allow just two signature declarations and no extra overhead? --or-- C. Something else? Please specify. |
|||
msg384289 - (view) | Author: Chaim Gewirtz (chaim422) | Date: 2021-01-03 17:47 | |
In your example, does Child foo call Parent foo? Because the intent is to use the parent's foo method. |
|||
msg384290 - (view) | Author: Yurii Karabas (uriyyo) * | Date: 2021-01-03 17:55 | |
> What is better? Sorry, I can't answer this question. I am a regular python user and I just tried to help with your issue. I believe we should wait for someone from core team to answer this question. > In your example, does Child foo call Parent foo? Because the intent is to use the parent's foo method. Sorry, I made a mistake, it definitely should call a parent method. A correct example will look like this: ``` class Parent: def foo(self, **kwargs): """Argument names of foo vary depending on the child class.""" class Child(Parent): def foo(self, a, b): super().foo(a=a, b=b) ``` But, the example above require more code to write, so a better option will be: ``` class Parent: def foo(self, **kwargs): """Argument names of foo vary depending on the child class.""" class Child(Parent): @overload def foo(self, a, b): pass @overload def foo(self, **kwargs): pass def foo(self, **kwargs): return super().foo(**kwargs) ``` I am not sure is it the perfect solution to solve your issue. Let's wait for someone from core team, so we can hear their opinion. |
|||
msg384292 - (view) | Author: Chaim Gewirtz (chaim422) | Date: 2021-01-03 18:26 | |
Thanks for your perspective. To summarize here is how my proposed enhancement might look in practice: class Parent: def foo(self, **kwargs): """Argument names of foo vary depending on the child class.""" class Child(Parent): @overload def foo(self, a, b): pass |
|||
msg384871 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2021-01-12 00:32 | |
I hesitate to add anything because you are exposing so much confusion. May I suggest that you ask about this on a user group first before proposing a new feature? One place that makes sense given that this is a type system feature would be this Gitter channel: https://gitter.im/python/typing |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:59:39 | admin | set | github: 86978 |
2021-01-12 00:32:35 | gvanrossum | set | nosy:
- levkivskyi messages: + msg384871 |
2021-01-08 21:40:09 | terry.reedy | set | nosy:
+ gvanrossum, levkivskyi |
2021-01-03 18:26:27 | chaim422 | set | messages: + msg384292 |
2021-01-03 17:55:40 | uriyyo | set | messages: + msg384290 |
2021-01-03 17:47:35 | chaim422 | set | messages: + msg384289 |
2021-01-03 17:43:20 | chaim422 | set | messages: + msg384288 |
2021-01-03 17:31:20 | uriyyo | set | messages: + msg384287 |
2021-01-03 17:25:06 | chaim422 | set | messages: + msg384286 |
2021-01-03 17:18:04 | uriyyo | set | messages: + msg384285 |
2021-01-03 16:40:47 | chaim422 | set | messages: + msg384284 |
2021-01-03 16:33:16 | chaim422 | set | messages: + msg384283 |
2021-01-03 11:53:09 | uriyyo | set | nosy:
+ uriyyo messages: + msg384265 |
2021-01-03 05:51:32 | chaim422 | create |