Narrowing type hint to just a few possibilities within a type /u/ladder_case Python Education

Let’s say I have a function

def signum(x: int | float) -> int: return 1 if x>0 else -1 if x<0 else 0 

which gives the sign of a number. And let’s say that it works perfectly, but I’m unsatisfied with the return type. There are a zillion integers, but none of them will ever come out of this function except 1, -1, or 0. It feels dishonest to say int and imply that one day we might get 725.

So my first instinct is some kind of enum like

from enum import IntEnum class Sign(IntEnum): POSITIVE = 1 NEGATIVE = -1 ZERO = 0 def signum(x: int | float) -> Sign: return Sign(1 if x>0 else -1 if x<0 else 0) 

and that works, plus it’s super clear. But it feels too heavyweight unless signs are conceptually important throughout my whole program.

So how about the Literal type, like

from typing import Literal def signum(x: int | float) -> Literal[1, -1, 0]: return 1 if x>0 else -1 if x<0 else 0 

And this seems good, but I’ve never seen anyone use Literal before. Maybe it has drawbacks I don’t know about.

If it is that good, maybe this could replace a lot of the places where I had been tempted to use enums. Since they’re just values, not fat enums like in Rust, they might as well just be values, right?

submitted by /u/ladder_case
[link] [comments]

​r/learnpython Let’s say I have a function def signum(x: int | float) -> int: return 1 if x>0 else -1 if x<0 else 0 which gives the sign of a number. And let’s say that it works perfectly, but I’m unsatisfied with the return type. There are a zillion integers, but none of them will ever come out of this function except 1, -1, or 0. It feels dishonest to say int and imply that one day we might get 725. So my first instinct is some kind of enum like from enum import IntEnum class Sign(IntEnum): POSITIVE = 1 NEGATIVE = -1 ZERO = 0 def signum(x: int | float) -> Sign: return Sign(1 if x>0 else -1 if x<0 else 0) and that works, plus it’s super clear. But it feels too heavyweight unless signs are conceptually important throughout my whole program. So how about the Literal type, like from typing import Literal def signum(x: int | float) -> Literal[1, -1, 0]: return 1 if x>0 else -1 if x<0 else 0 And this seems good, but I’ve never seen anyone use Literal before. Maybe it has drawbacks I don’t know about. If it is that good, maybe this could replace a lot of the places where I had been tempted to use enums. Since they’re just values, not fat enums like in Rust, they might as well just be values, right? submitted by /u/ladder_case [link] [comments] 

Let’s say I have a function

def signum(x: int | float) -> int: return 1 if x>0 else -1 if x<0 else 0 

which gives the sign of a number. And let’s say that it works perfectly, but I’m unsatisfied with the return type. There are a zillion integers, but none of them will ever come out of this function except 1, -1, or 0. It feels dishonest to say int and imply that one day we might get 725.

So my first instinct is some kind of enum like

from enum import IntEnum class Sign(IntEnum): POSITIVE = 1 NEGATIVE = -1 ZERO = 0 def signum(x: int | float) -> Sign: return Sign(1 if x>0 else -1 if x<0 else 0) 

and that works, plus it’s super clear. But it feels too heavyweight unless signs are conceptually important throughout my whole program.

So how about the Literal type, like

from typing import Literal def signum(x: int | float) -> Literal[1, -1, 0]: return 1 if x>0 else -1 if x<0 else 0 

And this seems good, but I’ve never seen anyone use Literal before. Maybe it has drawbacks I don’t know about.

If it is that good, maybe this could replace a lot of the places where I had been tempted to use enums. Since they’re just values, not fat enums like in Rust, they might as well just be values, right?

submitted by /u/ladder_case
[link] [comments] 

Leave a Reply

Your email address will not be published. Required fields are marked *