[Python-checkins] gh-74690: Document changes made to runtime-checkable protocols in 3.12 (#103348)
AlexWaygood
webhook-mailer at python.org
Fri Apr 7 17:06:44 EDT 2023
https://github.com/python/cpython/commit/644136563da653a93268cb8cae7e25ff691047a3
commit: 644136563da653a93268cb8cae7e25ff691047a3
branch: main
author: Alex Waygood <Alex.Waygood at Gmail.com>
committer: AlexWaygood <Alex.Waygood at Gmail.com>
date: 2023-04-07T22:06:37+01:00
summary:
gh-74690: Document changes made to runtime-checkable protocols in 3.12 (#103348)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra at gmail.com>
files:
A Misc/NEWS.d/next/Library/2023-04-07-15-09-26.gh-issue-74690.0f886b.rst
A Misc/NEWS.d/next/Library/2023-04-07-15-15-40.gh-issue-74690.un84hh.rst
M Doc/library/typing.rst
M Doc/whatsnew/3.12.rst
diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst
index 8728ca7b6b35..03ff259bbdf7 100644
--- a/Doc/library/typing.rst
+++ b/Doc/library/typing.rst
@@ -1598,15 +1598,6 @@ These are not used in annotations. They are building blocks for creating generic
import threading
assert isinstance(threading.Thread(name='Bob'), Named)
- .. versionchanged:: 3.12
- The internal implementation of :func:`isinstance` checks against
- runtime-checkable protocols now uses :func:`inspect.getattr_static`
- to look up attributes (previously, :func:`hasattr` was used).
- As a result, some objects which used to be considered instances
- of a runtime-checkable protocol may no longer be considered instances
- of that protocol on Python 3.12+, and vice versa.
- Most users are unlikely to be affected by this change.
-
.. note::
:func:`!runtime_checkable` will check only the presence of the required
@@ -1628,6 +1619,24 @@ These are not used in annotations. They are building blocks for creating generic
.. versionadded:: 3.8
+ .. versionchanged:: 3.12
+ The internal implementation of :func:`isinstance` checks against
+ runtime-checkable protocols now uses :func:`inspect.getattr_static`
+ to look up attributes (previously, :func:`hasattr` was used).
+ As a result, some objects which used to be considered instances
+ of a runtime-checkable protocol may no longer be considered instances
+ of that protocol on Python 3.12+, and vice versa.
+ Most users are unlikely to be affected by this change.
+
+ .. versionchanged:: 3.12
+ The members of a runtime-checkable protocol are now considered "frozen"
+ at runtime as soon as the class has been created. Monkey-patching
+ attributes onto a runtime-checkable protocol will still work, but will
+ have no impact on :func:`isinstance` checks comparing objects to the
+ protocol. See :ref:`"What's new in Python 3.12" <whatsnew-typing-py312>`
+ for more details.
+
+
Other special directives
""""""""""""""""""""""""
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index 3a12fb20c43c..66e40ef7326c 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -422,6 +422,8 @@ tempfile
The :class:`tempfile.NamedTemporaryFile` function has a new optional parameter
*delete_on_close* (Contributed by Evgeny Zorin in :gh:`58451`.)
+.. _whatsnew-typing-py312:
+
typing
------
@@ -441,6 +443,39 @@ typing
vice versa. Most users are unlikely to be affected by this change.
(Contributed by Alex Waygood in :gh:`102433`.)
+* The members of a runtime-checkable protocol are now considered "frozen" at
+ runtime as soon as the class has been created. Monkey-patching attributes
+ onto a runtime-checkable protocol will still work, but will have no impact on
+ :func:`isinstance` checks comparing objects to the protocol. For example::
+
+ >>> from typing import Protocol, runtime_checkable
+ >>> @runtime_checkable
+ ... class HasX(Protocol):
+ ... x = 1
+ ...
+ >>> class Foo: ...
+ ...
+ >>> f = Foo()
+ >>> isinstance(f, HasX)
+ False
+ >>> f.x = 1
+ >>> isinstance(f, HasX)
+ True
+ >>> HasX.y = 2
+ >>> isinstance(f, HasX) # unchanged, even though HasX now also has a "y" attribute
+ True
+
+ This change was made in order to speed up ``isinstance()`` checks against
+ runtime-checkable protocols.
+
+* The performance profile of :func:`isinstance` checks against
+ :func:`runtime-checkable protocols <typing.runtime_checkable>` has changed
+ significantly. Most ``isinstance()`` checks against protocols with only a few
+ members should be at least 2x faster than in 3.11, and some may be 20x
+ faster or more. However, ``isinstance()`` checks against protocols with seven
+ or more members may be slower than in Python 3.11. (Contributed by Alex
+ Waygood in :gh:`74690` and :gh:`103193`.)
+
sys
---
diff --git a/Misc/NEWS.d/next/Library/2023-04-07-15-09-26.gh-issue-74690.0f886b.rst b/Misc/NEWS.d/next/Library/2023-04-07-15-09-26.gh-issue-74690.0f886b.rst
new file mode 100644
index 000000000000..0a103ae11970
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-04-07-15-09-26.gh-issue-74690.0f886b.rst
@@ -0,0 +1,3 @@
+The members of a runtime-checkable protocol are now considered "frozen" at
+runtime as soon as the class has been created. See
+:ref:`"What's new in Python 3.12" <whatsnew-typing-py312>` for more details.
diff --git a/Misc/NEWS.d/next/Library/2023-04-07-15-15-40.gh-issue-74690.un84hh.rst b/Misc/NEWS.d/next/Library/2023-04-07-15-15-40.gh-issue-74690.un84hh.rst
new file mode 100644
index 000000000000..48f11aac692d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-04-07-15-15-40.gh-issue-74690.un84hh.rst
@@ -0,0 +1,8 @@
+The performance of :func:`isinstance` checks against
+:func:`runtime-checkable protocols <typing.runtime_checkable>` has been
+considerably improved for protocols that only have a few members. To achieve
+this improvement, several internal implementation details of the
+:mod:`typing` module have been refactored, including
+``typing._ProtocolMeta.__instancecheck__``,
+``typing._is_callable_members_only``, and ``typing._get_protocol_attrs``.
+Patches by Alex Waygood.
More information about the Python-checkins
mailing list