- Notifications
You must be signed in to change notification settings - Fork263
-
Consider a function taking one parameter that always returns an object of the same type as its only parameter, e.g., defmystrip(x):ifisinstance(x,str):returnx.strip()returnx While it is straight-forward to annotate the signature using a importtypingT=typing.TypeVar("T")defmystrip(x:T)->T:ifisinstance(x,str):returnx.strip()returnx mypy 1.9.0: I understand the problem that typecheckers are obviously not establishing a connection between the narrowing I believe that such defensive functions implementing a "perform certain type-preserving normalization on some values, return anything else unchanged" pattern is quite common in python. Ho do I annotate it to make the typecheckers happy? (apart from the trivial |
BetaWas this translation helpful?Give feedback.
All reactions
Replies: 3 comments 2 replies
-
Or is the problem more subtle? Is it that in the |
BetaWas this translation helpful?Give feedback.
All reactions
-
I found that explicit casting to defmystrip(x:T)->T:ifisinstance(x,str):returntype(x)(x.strip())returnx Even though I wouldn't call this "idiomatic python", it seems to work. |
BetaWas this translation helpful?Give feedback.
All reactions
-
In principle your annotated function is correct. This kind of narrowing seems safe to me, and I would consider this type of narrowing a desirable feature for type checkers, although I'm not sure how easy it would be to implement. It's possible that there are already issues open for the type checkers. If not, I'm sure that issues would be appreciated. In the meantime I would work around this using importtypingT=typing.TypeVar("T")defmystrip(x:T)->T:ifisinstance(x,str):returntyping.cast(T,x.strip())returnx |
BetaWas this translation helpful?Give feedback.
All reactions
-
What about subclasses of This code typechecks, but it fails at runtime (tested on CPython 3.12.11 andpyright playground): fromtypingimportcast,reveal_typedefmystrip[T](x:T)->T:ifisinstance(x,str):returncast(T,x.strip())returnxclassName(str):defgreet(self)->None:print(f"Hello,{self}!")name=mystrip(Name(" World! "))reveal_type(name)# pyright thinks it's `Name`, but CPython says it's a `str`name.greet()# AttributeError! Could this be a problem / soundness hole (introduced by the |
BetaWas this translation helpful?Give feedback.
All reactions
-
You are right, this could actually be the problem. |
BetaWas this translation helpful?Give feedback.