[Python-checkins] [3.9] bpo-4442: Document use of __new__ for subclasses of immutable types (GH-27866) (GH-27900)

ambv webhook-mailer at python.org
Sun Aug 22 16:14:36 EDT 2021


https://github.com/python/cpython/commit/ac87b07a10e0ba2834e8de9cf0ea29a40fd882b1
commit: ac87b07a10e0ba2834e8de9cf0ea29a40fd882b1
branch: 3.9
author: Łukasz Langa <lukasz at langa.pl>
committer: ambv <lukasz at langa.pl>
date: 2021-08-22T22:14:25+02:00
summary:

[3.9] bpo-4442:  Document use of __new__ for subclasses of immutable types (GH-27866) (GH-27900)

(cherry picked from commit eec340ea3af27887fcaac4029ebdee99f3713bff)

Co-authored-by: Raymond Hettinger <rhettinger at users.noreply.github.com>

files:
M Doc/faq/programming.rst

diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst
index ad51bb6ebf5952..04d6592aeccdbe 100644
--- a/Doc/faq/programming.rst
+++ b/Doc/faq/programming.rst
@@ -1828,6 +1828,54 @@ For example, here is the implementation of
         return False
 
 
+How can a subclass control what data is stored in an immutable instance?
+------------------------------------------------------------------------
+
+When subclassing an immutable type, override the :meth:`__new__` method
+instead of the :meth:`__init__` method.  The latter only runs *after* an
+instance is created, which is too late to alter data in an immutable
+instance.
+
+All of these immutable classes have a different signature than their
+parent class:
+
+.. testcode::
+
+    from datetime import date
+
+    class FirstOfMonthDate(date):
+        "Always choose the first day of the month"
+        def __new__(cls, year, month, day):
+            return super().__new__(cls, year, month, 1)
+
+    class NamedInt(int):
+        "Allow text names for some numbers"
+        xlat = {'zero': 0, 'one': 1, 'ten': 10}
+        def __new__(cls, value):
+            value = cls.xlat.get(value, value)
+            return super().__new__(cls, value)
+
+    class TitleStr(str):
+        "Convert str to name suitable for a URL path"
+        def __new__(cls, s):
+            s = s.lower().replace(' ', '-')
+            s = ''.join([c for c in s if c.isalnum() or c == '-'])
+            return super().__new__(cls, s)
+
+The classes can be used like this:
+
+.. doctest::
+
+    >>> FirstOfMonthDate(2012, 2, 14)
+    FirstOfMonthDate(2012, 2, 1)
+    >>> NamedInt('ten')
+    10
+    >>> NamedInt(20)
+    20
+    >>> TitleStr('Blog: Why Python Rocks')
+    'blog-why-python-rocks'
+
+
 Modules
 =======
 



More information about the Python-checkins mailing list