-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document we're not tracking relationships between symbols #16018
Document we're not tracking relationships between symbols #16018
Conversation
- :py:func:`issubclass` like in :code:`issubclass(cls, MyClass)` will narrow ``cls`` to be ``Type[MyClass]`` | ||
- :py:class:`type` like in :code:`type(obj) is int` will narrow ``obj`` to have ``int`` type | ||
- :py:func:`callable` like in :code:`callable(obj)` will narrow object to callable type | ||
- :code:`obj is not None` will narrow object to its :ref:`non-optional form <strict_optional>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strangely we didn't mention this
docs/source/type_narrowing.rst
Outdated
Limitations of narrowing | ||
~~~~~~~~~~~~~~~~~~~~~~~~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hope this is the right place. I wanted it to have a heading, to make it easy to refer people, but it's also a bit strange that it comes as a topic in the same hierarchy and right before "is_subclass" and "callable".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make it a heading and move it to the bottom of the page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for writing this up!
docs/source/type_narrowing.rst
Outdated
Limitations of narrowing | ||
~~~~~~~~~~~~~~~~~~~~~~~~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make it a heading and move it to the bottom of the page.
docs/source/type_narrowing.rst
Outdated
return 'spam' | ||
|
||
Tracking these sort of cross-variable conditions in a type checker would add significant complexity | ||
and performance overhead and would be computationally infeasible in all but the most basic cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and performance overhead and would be computationally infeasible in all but the most basic cases. | |
and performance overhead. |
Claim feels a little too strong, first half of the sentence says enough.
docs/source/type_narrowing.rst
Outdated
Tracking these sort of cross-variable conditions in a type checker would add significant complexity | ||
and performance overhead and would be computationally infeasible in all but the most basic cases. | ||
|
||
You may override the type checker with a :ref:`cast <casts>`, or rewrite the function to be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may override the type checker with a :ref:`cast <casts>`, or rewrite the function to be | |
You may override the type checker with an ``assert`` or :ref:`cast <casts>`, or rewrite the function to be |
When I run into this, assert is usually more ergonomic. It's also safer than cast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably would phrase as "help the type checker with an assert
", but I'm not sure it'll be more ergonomic in this case. Maybe I'm tired and missing something obvious?
cast:
def f(a: str | None, b: str | None) -> str:
if a is not None or b is not None:
return a or cast(str, b)
return 'spam'
assert:
def f(a: str | None, b: str | None) -> str:
if a is not None or b is not None:
if a:
return a
assert b is not None
return b
return 'spam'
third option:
def f(a: str | None, b: str | None) -> str:
if a is not None or b is not None:
return a or b or 'impossible'
return 'spam'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, not more ergonomic in this case, but better in the cases where I usually run into this. But maybe I dislike cast more than most people :-)
I'd do assert a or b; return a or b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert a or b
doesn't help you either because we don't narrow conditionally. (Also, in this case you'd get more than you'd bargain for, as empty b
would assert.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh oops, I guess you'd have to do ret = a or b; assert ret is not None; return ret
Fixes #15653.
I did not use @erictraut's "quantum entanglement" metaphor, though I find it to be quite illustrative :)