@@ -367,19 +367,38 @@ above example:
367
367
Complex type tests
368
368
------------------
369
369
370
- Mypy can usually infer the types correctly when using :py:func: `isinstance <isinstance> `
371
- type tests, but for other kinds of checks you may need to add an
370
+ Mypy can usually infer the types correctly when using :py:func: `isinstance <isinstance> `,
371
+ :py:func: `issubclass <issubclass> `,
372
+ or ``type(obj) is some_class `` type tests,
373
+ and even user-defined type guards,
374
+ but for other kinds of checks you may need to add an
372
375
explicit type cast:
373
376
374
377
.. code-block :: python
375
378
376
- def f (o : object ) -> None :
377
- if type (o) is int :
378
- o = cast(int , o)
379
- g(o + 1 ) # This would be an error without the cast
380
- ...
381
- else :
382
- ...
379
+ from typing import Sequence, cast
380
+
381
+ def find_first_str (a : Sequence[object ]) -> str :
382
+ index = next ((i for i, s in enumerate (a) if isinstance (s, str )), - 1 )
383
+ if index < 0 :
384
+ raise ValueError (' No str found' )
385
+
386
+ found = a[index] # Has `object` type, despite the fact that we know it is `str`
387
+ return cast(str , found) # So, we need an explicit cast to make mypy happy
388
+
389
+ Alternatively, you can use ``assert `` statement together with some
390
+ of the supported type inference techniques:
391
+
392
+ .. code-block :: python
393
+
394
+ def find_first_str (a : Sequence[object ]) -> str :
395
+ index = next ((i for i, s in enumerate (a) if isinstance (s, str )), - 1 )
396
+ if index < 0 :
397
+ raise ValueError (' No str found' )
398
+
399
+ found = a[index] # Has `object` type, despite the fact that we know it is `str`
400
+ assert isinstance (found, str ) # Now, `found` will be narrowed to `str` subtype
401
+ return found # No need for the explicit `cast()` anymore
383
402
384
403
.. note ::
385
404
@@ -390,19 +409,11 @@ explicit type cast:
390
409
runtime. The cast above would have been unnecessary if the type of
391
410
``o `` was ``Any ``.
392
411
393
- Mypy can't infer the type of ``o `` after the :py:class: `type() <type> ` check
394
- because it only knows about :py:func: `isinstance ` (and the latter is better
395
- style anyway). We can write the above code without a cast by using
396
- :py:func: `isinstance `:
412
+ .. note ::
397
413
398
- .. code-block :: python
414
+ You can read more about type narrowing techniques here.
399
415
400
- def f (o : object ) -> None :
401
- if isinstance (o, int ): # Mypy understands isinstance checks
402
- g(o + 1 ) # Okay; type of o is inferred as int here
403
- ...
404
-
405
- Type inference in mypy is designed to work well in common cases, to be
416
+ Type inference in Mypy is designed to work well in common cases, to be
406
417
predictable and to let the type checker give useful error
407
418
messages. More powerful type inference strategies often have complex
408
419
and difficult-to-predict failure modes and could result in very
@@ -621,7 +632,7 @@ You can install the latest development version of mypy from source. Clone the
621
632
sudo python3 -m pip install --upgrade .
622
633
623
634
Variables vs type aliases
624
- -----------------------------------
635
+ -------------------------
625
636
626
637
Mypy has both type aliases and variables with types like ``Type[...] `` and it is important to know their difference.
627
638
@@ -662,7 +673,7 @@ Mypy has both type aliases and variables with types like ``Type[...]`` and it is
662
673
def fun2 (x : tp) -> None : ... # error: Variable "__main__.tp" is not valid as a type
663
674
664
675
Incompatible overrides
665
- ------------------------------
676
+ ----------------------
666
677
667
678
It's unsafe to override a method with a more specific argument type,
668
679
as it violates the `Liskov substitution principle
@@ -773,7 +784,6 @@ False:
773
784
If you use the :option: `--warn-unreachable <mypy --warn-unreachable> ` flag, mypy will generate
774
785
an error about each unreachable code block.
775
786
776
-
777
787
Narrowing and inner functions
778
788
-----------------------------
779
789
0 commit comments