◐ Shell
clean mode source ↗

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.

merwok

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().

merwok

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!

rhettinger

@bedevere-bot

There's a new commit after the PR has been approved.

@rhettinger: please review the changes made to this pull request.

@vstinner

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.

csm10495

----

* 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?

@vstinner

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}

@vstinner

@serhiy-storchaka

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.

Reviewers

@merwok merwok merwok left review comments

@ericvsmith ericvsmith Awaiting requested review from ericvsmith ericvsmith is a code owner

@pganssle pganssle Awaiting requested review from pganssle pganssle is a code owner

@abalkin abalkin Awaiting requested review from abalkin

@markshannon markshannon Awaiting requested review from markshannon markshannon is a code owner

@rhettinger rhettinger Awaiting requested review from rhettinger rhettinger is a code owner

+1 more reviewer

@csm10495 csm10495 csm10495 left review comments

Reviewers whose approvals may not affect merge requirements

Labels