-
Notifications
You must be signed in to change notification settings - Fork 240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow float("inf")
and float("-inf")
in literals
#1160
Comments
|
We don't. PEP 586 lists all valid types for literals, and float isn't among them. |
Yes, float literals are not supported. Also, call expressions are not (nor should be) allowed in type annotations. It's important that we keep type annotation expressions simple — for reasons of consistency and evaluation performance. |
An approach that avoids call expressions could be to allow Not sure this is worth changing in the type system though. In the OP's case, they could just write |
I currently am designing an api which looks like: def redirect_to(self, somewhere_else: Self, * for: timedelta | Literal[float("inf")]): ... Because I want to make sure people don't have to deal with the units they are passing. Specifying this is in seconds I think at least is a bit annoying especially if the endpoint I'm calling changes it's units without warning. |
@JelleZijlstra Just a nitpick but "they could just write @erictraut That makes sense, would it be less complex to do what Jelle suggests? Although I realize this feature would probably have a quite low "return on investment" in terms of gained typing accuracy per time invested in building and specifying it. |
My code has |
Just my 2 cents, I am no professional on the matter. Could NegativeInfinity: TypeAlias = float
PositiveInfinity: TypeAlias = float
Infinity: NegativeInfinity | PositiveInfinity
NotANumber: TypeAlias = float
# idk if this is even feasable, or even needed.
# Maybe it could be useful in some arithmetic cases, or when delaying.
# Reminds me of LiteralString for its safety applications.
FiniteFloat: TypeAlias = float
float("-inf") # type: NegativeInfinity # type: Literal[NegativeInfinity]
float("+inf") # type: PositiveInfinity # type: Literal[PositiveInfinity]
float("inf") # type: PositiveInfinity # type: Literal[PositiveInfinity]
float("nan") # type: NotANumber # type: Literal[NotANumber] I agree this is "low return on investment". Still something I would like as a type user. |
For OP's use case, maybe a "comparable-to-int" protocol could work? This is probably a good type to choose for the pyyaml PR that got linked here |
@hauntsaninja No that would not have worked, as already repeated, the real usecase really required int. |
Here is my use case for the same feature request: I am the author of NoGraphs, a library dealing with implicit graphs. Here, the application can choose what data types to use (including rare choices like Decimal or arbitrary precision floats), optionally made type-safe by type annotations. A common choice for graph applications is to use int for edge weights and distances. But just because an infinity value is needed as default, the annotation needs to be int | float (or just float). This is disturbing from the perspective of the application, because it uses int to exclude precision problems - and then, float occurs "everywhere" in the application... (I hope, this can be helpful for the discussion - I am no specialist in the topic. I might be completely wrong...) |
Perhaps a better way to handle such an API is to use a dedicated sentinel value rather than |
I think so, too. Thanks. I also agree with the perspective w.r.t. the type system. Furthermore, in the use case, In some cases, these alternatives might also have disadvantages: Since Although: Solving the issue might just be not worth it, or too complicated, or would have side effects... (My perspective and knowledge about such topics is very limited. And I can perfectly live without inf as literal.) |
@HeWeMel You can create a new This way users of your library who also want strict typing can pass an instance of That being said, I would also prefer being able to simply use a literal infinity directly from python's type system. 😄 |
@Avasam, this sounds like a very good idea. I will definitely try this. Thanks! |
@erictraut Please note that such usage of None is acknowledged in the original post of this topic. I do hear you that it's not worth spoiling the otherwise simpler syntax of current type hints for this rather special case though. It's a minor flaw that I think we can live with. |
In mathematical contexts ``inf` is a relatively common default:
So a |
How about using enum? class Bound(float, enum.Enum):
Inf = float("inf")
NegInf = float("-inf") Constants could be easily extracted via Literal wrapping and comparison also works. |
This would really only be practical if the enums were "batteries included" in base python. Having every library define their own Enum and then, for correct type checking, require users to use that specific implementation is burdensome. I've tried and abandoned this in personal projects. |
Agree. I considered adding this to |
As already said, using positive infinity as a default value for integers is a very common and natural choice. Using types in Python has for me two benefits:
Writing
while valid, is both less explicit, and less safe than On the other hand, using Perhaps using a custom Generally speaking, infinities are treated as second class citizens in Python (I had to patch ` |
I have been frequently using positive and negative infinity as default values for values that should otherwise be
int
s. Because of Python's duck typing this is a convenient pattern that sometimes allows reducing some special-casing logic.vs
Would it be feasible to special-case the expressions
float("inf")
andfloat("-inf")
and make type-checkers regard them as literal values, even though they aren't strictly speaking language-level literals?For posterity, PEP 586 mentions this with:
So I guess what I'm asking here is: am I an odd duckling or could it be worth considering +/- infinity as legal values in literal types?
The text was updated successfully, but these errors were encountered: