Skip to content

gh-102936: typing: document performance pitfalls of protocols decorated with @runtime_checkable #102937

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

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1584,16 +1584,32 @@ These are not used in annotations. They are building blocks for creating generic

assert isinstance(open('/some/file'), Closable)

@runtime_checkable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think many users aren't too familiar with OSError's constructor / we can't use kwargs and it's unclear what the second argument is. Maybe we could use int and HasNumerator instead?

(I know it's not writeable, but OSError's errno also is maybe not writeable? Writing to errno doesn't affect repr)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was really struggling to think of a good example for this! I'll ponder some more and see if I can come up with something better...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps unsurprisingly, not too many good cases of writeable attributes in stdlib. Maybe Thread.name? It's explicitly documented as something you can write to.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works! I'll make the change tomorrow (it's late here)

class Named(Protocol):
name: str

import threading
assert isinstance(threading.Thread(name='Bob'), Named)

.. note::

:func:`runtime_checkable` will check only the presence of the required
methods, not their type signatures. For example, :class:`ssl.SSLObject`
:func:`!runtime_checkable` will check only the presence of the required
methods or attributes, not their type signatures or types.
For example, :class:`ssl.SSLObject`
is a class, therefore it passes an :func:`issubclass`
check against :data:`Callable`. However, the
``ssl.SSLObject.__init__`` method exists only to raise a
:exc:`TypeError` with a more informative message, therefore making
it impossible to call (instantiate) :class:`ssl.SSLObject`.

.. note::

An :func:`isinstance` check against a runtime-checkable protocol can be
surprisingly slow compared to an ``isinstance()`` check against
a non-protocol class. Consider using alternative idioms such as
:func:`hasattr` calls for structural checks in performance-sensitive
code.

.. versionadded:: 3.8

Other special directives
Expand Down