gh-108751: Add copy.replace() function by serhiy-storchaka · Pull Request #108752 · python/cpython
Conversation
It creates a modified copy of an object by calling the object's __replace__() method. It is a generalization of dataclasses.replace(), named tuple's _replace() method and replace() methods in various classes, and supports all these stdlib classes.
| single: __replace__() (replace protocol) | ||
|
|
||
| Function :func:`replace` is more limited than :func:`copy` and :func:`deepcopy`, | ||
| and only supports named tuples, dataclasses, and other classes which |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| and only supports named tuples, dataclasses, and other classes which | |
| and only supports :term:`named tuples <named tuple>`, :mod:`dataclasses`, and other classes which |
(I haven’t double checked if named tuple or namedtuple is the right key)
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it does not support named tuples in general. It currently only supports named tuples created by collections.namedtuple().
| func = getattr(cls, '__replace__', None) | ||
| if func is None: | ||
| raise TypeError(f"replace() does not support {cls.__name__} objects") | ||
| return func(obj, **changes) |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a cool feature for very little code!
There's a new commit after the PR has been approved.
@rhettinger: please review the changes made to this pull request.
This change introduced a regression: see issue #109052.
With this change, test_sys_settrace started to crash. I don't know if the bug already existed before and was hidden, or if the Objects/codeobject.c change really introduced a regression.
| ---- | ||
|
|
||
| * Add :func:`copy.replace` function which allows to create a modified copy of | ||
| an object, which is especially usefule for immutable objects. |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usefule -> useful
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Do you mind to create a PR to fix this typo?
Would it make sense to add support for dict?
>>> d={'x': 1} >>> copy.replace(d, x=2) TypeError: replace() does not support dict objects
It would be an alternative to:
>>> d={'x': 1} >>> dict(d, x=2) {'x': 2} >>> {**d, 'x': 2} {'x': 2}
Would it make sense to add support for dict?
Perhaps no, because it erodes the difference between an object and a dict (as in JavaScript).
And you already have other ways to do this with dicts.