builtins: preparation for having the number types derive from the numbers ABCs #3108
builtins: preparation for having the number types derive from the numbers ABCs #3108bluetech wants to merge 3 commits intopython:masterfrom
Conversation
cb4e876 to
eec07e0
Compare
|
Hmm, this causes mypy with the new semantic analyzer to crash:
|
|
I like the first three commits. I am a bit wary of deriving the built-in number types from the ABCs, though. The real classes are not derived from the ABCs and probably use |
|
@srittau Thanks for taking a look, I'll remove the last commit from this PR and open an issue to discuss it. |
eec07e0 to
919609d
Compare
|
@srittau Updated. Will open the issue a bit later. |
| def __round__(self, ndigits: int) -> float: ... | ||
| def __trunc__(self) -> int: ... | ||
| def __floor__(self) -> int: ... | ||
| def __ceil__(self) -> int: ... |
There was a problem hiding this comment.
The last two don't seem to exist (which surprised me):
Python 3.7.3 (default, Jun 3 2019, 18:27:33)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> x = 3.0
>>> x.__trunc__()
3
>>> x.__floor__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'float' object has no attribute '__floor__'
>>> x.__ceil__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'float' object has no attribute '__ceil__'There was a problem hiding this comment.
Hmm, should have checked all of them.
I looked into cpython code, and what I understand is that math.floor (same for math.ceil) has a special case for floats, or rather types that can be converted to float (implement __float__()). In these cases, if __floor__ is not defined, it converts to float and does the operation directly.
import math
class X:
def __float__(self):
return 5.4
#def __floor__(self):
# return 10
print(math.floor(X()))Commented it prints 5, uncommented it prints 10.
So I think that, given numbers.Real already requires __float__, we can just diverge from the actual definition of numbers.Real and remove __floor__ and __ceil__ from it in typeshed. WDYT? The numbers.Real doc only requires math.floor to work.
| @abstractmethod | ||
| def __round__(self, ndigits: Optional[int] = ...): ... | ||
| @overload | ||
| def __round__(self, ndigits: None = ...): ... |
There was a problem hiding this comment.
Not sure why this needs overloads.
There was a problem hiding this comment.
The idea is to have the same form as float above. Once this stub is filled the return types of the two overloads will be different, I think.
| def __rmod__(self, x: int) -> int: ... | ||
| def __rdivmod__(self, x: int) -> Tuple[int, int]: ... | ||
| def __pow__(self, x: int) -> Any: ... # Return type can be int or float, depending on x. | ||
| def __pow__(self, x: int, modulo: Optional[int] = ...) -> Any: ... # Return type can be int or float, depending on x. |
There was a problem hiding this comment.
The arguments are actually positional-only
There was a problem hiding this comment.
Is there some special way to encode this?
There was a problem hiding this comment.
Start the names with two underscores, like __modulo.
|
I stripped the useful parts of this PR to separate PRs and opened an issue about the |
This should make e.g. this work:(See comment #3108 (comment)).This PR has some preparation commits before making the change. Should be easier to review each one separately.