Type cast in Python

Jun 01, 2020 00:15


Originally published at www.ikriv.com. Please leave any comments there.

TL;DR:
Python type cast looks like an assertion:

# Python x = expression_returning_Base assert isinstance(x, Derived)
This corresponds to Java or C#

// Java Derived x = (Derived)expression_returning_Base;
In languages like Java and C++, it is a common situation when at runtime we know we have an object of type Derived, but the compiler thinks it is of type Base, so we must explicitly cast the object reference to type Derived before the compiler would allow us to use any Derived-specific properties or methods.

Python, being a dynamic type language, does not have this problem: you just call whatever methods you feel right. If such methods are not found at runtime, an exception will occur.

# Python class Base: def foo(self) -> None: print("Base.foo()") class Derived(Base): def bar(self) -> None: print("Derived.bar()") def func() -> Base: return Derived() x = func() x.bar() # it works, but fails the type check
However, the situation changes in presence of type hints: x.bar() above won’t pass the type check, claiming that "Base" has no attribute "bar". This does not prevent us from running the code, but may, say, prevent from committing it to a repo if type checks are strictly enforced.

If we simply declare x of type Derived, it does not help:

x : Derived = func() # typecheck error x.bar()
The error is Incompatible types in assignment (expression has type "Base", variable has type "Derived").

To convince the type checker that x is indeed of type Derived, we need an assertion:

x = func() assert isinstance(x, Derived) # type cast x.bar()
Note, that the situation may become complicated if you apply type assertion to attributes. Unlike C++ or Java, type checking is not part of the language runtime, so whether the assert will work depends on the type checker.

x = type('test', (), {})() # empty object of custom type x.y = func() assert isinstance(x.y, Derived) x.y.bar() # May or may not pass the type check
Specifically, current version of mypy recognizes this assert, but pyre does not.

uncategorized

Previous post Next post
Up