We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Precise Type Hints with Literals and Generics step 3 of 26
Turn an Unknown Value into an int
Your service reads settings from a file that anyone can edit. A setting that
should be a whole number might arrive as 7, "7", 7.0, True or None.
You write one function that accepts the safe forms and rejects the rest.
assert solve([7, "007", "-5", 2.0, True, " 42 ", None]) == [
"ok:7", "ok:7", "ok:-5", "ok:2",
"reject:bool", "reject:str", "reject:NoneType",
]
Any, object and Never
Anyswitches off checking for that value, and mypy accepts any operation on it. The starter'scoerce_int(value: Any) -> Anyreturns its input without checking it, and mypy reports no error.objectalso accepts any value, but mypy allows only what every object supports, such asstr(value). To callvalue.is_integer(), first narrow withisinstance(value, float). Soobjectis the right type for a value you have not checked yet.Neveris the type with no values. A function annotated-> Nevernever returns normally, for example because it always raises. The exercise "Make mypy Report an Unhandled Event with assert_never" uses it.
What to write
coerce_int(value: object) -> int accepts three kinds of value:
| Input | Rule |
|---|---|
int |
Return it. Reject bool. |
str |
Accept one or more ASCII digits, with at most one - in front. |
float |
Accept only when value.is_integer() is true. |
- Raise
TypeErrorfor every other value. Any message will do. - Check
boolbeforeint.boolis a subclass ofint, soisinstance(True, int)is true. - For a string, remove one leading
-if there is one, and call the restbody. Accept the string only whenbody.isascii() and body.isdecimal()is true. - For a float, check
is_integer()before you callint(), becauseint(7.5)drops the fraction and returns7.is_integer()is false for fractions, infinity and NaN. - Replace the starter's
Anyannotations withobjectandint. Narrow withisinstance, and use nocastor# type: ignore.
solve(values: list[object]) -> list[str] returns one string per value, in
order:
"ok:<n>"for an accepted value, withnin decimal and no leading zeros."reject:<name>"for a rejected value, where the name istype(value).__name__.
By default, Python's int() and str() refuse numbers longer than 4300
digits, and the tests include longer ones. So convert a validated string with the starter's
_parse_decimal, and format each result in solve with _decimal_text.
Edge cases
coerce_intrejects" 42 ","+5","1_0","0x10",""and"-", thoughint()accepts the first three.- It also rejects
"٣","1"and"³".isdigit()alone accepts all three, andisdecimal()alone accepts the first two. "007"gives"ok:7"."-000"and-0.0give"ok:0".- An empty list gives
[].
Going further
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.