diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2021-08-22 19:49:24 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-22 19:49:24 (GMT) |
commit | 0627918f0b69a15aa16e4ccbb5d8eaae4f6a2caf (patch) | |
tree | d4175469734433f21465cd1a1f702ac3529b79f9 | |
parent | 8e90f15ac88c66ddb7b084bb5780a126d35168af (diff) | |
download | cpython-0627918f0b69a15aa16e4ccbb5d8eaae4f6a2caf.zip cpython-0627918f0b69a15aa16e4ccbb5d8eaae4f6a2caf.tar.gz cpython-0627918f0b69a15aa16e4ccbb5d8eaae4f6a2caf.tar.bz2 |
bpo-4442: Document use of __new__ for subclasses of immutable types (GH-27866)
(cherry picked from commit eec340ea3af27887fcaac4029ebdee99f3713bff)
Co-authored-by: Raymond Hettinger <rhettinger@users.noreply.github.com>
-rw-r--r-- | Doc/faq/programming.rst | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index af4b489..ef80808 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -1826,6 +1826,55 @@ For example, here is the implementation of return True 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' + + How do I cache method calls? ---------------------------- |