Why does copy_with
exists? Why not use copy.replace
which exists for exactly that usecase and is compatible with dataclasses?
copy_with
can be typed and doesn’t need an import. It might not be a strong enough reason to keep it, but it’s certainly enough for me to prefer some variant of an object specific copy_with
/replace
over copy.replace
.
But copy_with
is also a maintenance burden that needs to be kept correct forever, whereas replace
just works. And the typing aspect is irrelevant or in favor of replace
since type checker know about that function specifically, which is half of the reason it was introduced.
Saving an import, sure, I guess, but that is imo a very weak argument for keeping around completely redundant code that has a chance to break.
dataclasses
depends on copy
already so the module is already imported and not using it isn’t saving any import time.
That said I’m not sure why you wouldn’t use dataclasses.replace
which doesn’t have the minor issue of needing to import another module.
I agree. As I said in my comment:
I don’t think saving an import or lack of typing justifies having a redundant method. But as a user, I can’t help but prefer a copy_with
method that’s both easier to reach and is likely typed, giving me both autocomplete and catching errors in the editor.
copy.replace
is simply typed as Any
:
def replace(obj: _SR, /, **changes: Any) -> _SR: ...
I’ll emphasize again that I’m not arguing to keep the method. A unified protocol like __replace__
is very welcome and was designed to solve this exact problem. It’s unfortunate that it can’t be typed today, but I can live with that.
Somewhat interestingly, mypy
will correctly give an error if dataclasses.replace
is used with a field that doesn’t exist or with an argument of the wrong type, but won’t give the same error if you use copy.replace
.
[Edit: Original playground link was missing the copy.replace
examples.]
That’s a consequence of people arguing for mypy to intentionally be unsound on __replace__