Skip to content

gh-108751: Add copy.replace() function #108752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 6, 2023

Conversation

serhiy-storchaka
Copy link
Member

@serhiy-storchaka serhiy-storchaka commented Sep 1, 2023

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.


📚 Documentation preview 📚: https://cpython-previews--108752.org.readthedocs.build/

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
Copy link
Member

@merwok merwok Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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)

Copy link
Member Author

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)
Copy link
Member

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!

@serhiy-storchaka serhiy-storchaka merged commit 6f3c138 into python:main Sep 6, 2023
@serhiy-storchaka serhiy-storchaka deleted the copy-replace branch September 6, 2023 20:55
@bedevere-bot
Copy link

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

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

@vstinner
Copy link
Member

vstinner commented Sep 7, 2023

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usefule -> useful

Copy link
Member Author

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
Copy link
Member

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
Copy link
Member

Nice feature.

@serhiy-storchaka
Copy link
Member Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants