Eugene Toder added the comment:
Properly supporting subclasses in replace() is hard, at least without some
cooperation from subclasses. For a proper replace()
x.replace(a=newval).b == x.b
should hold for every b not dependent on a, including ones added by subclasses.
That is, it should replicate subclass state. Arguably, ideal replace() would
also allow changing attributes defined by subclasses -- otherwise subclasses
need to override it anyway, and all this effort was for nothing.
The best I can think of is to assume that subclasses are immutable and all
"primary" properties are settable via constructor arguments with the same
names. Then replace() can be implemented like this:
def replace(self, *args, **kwargs):
sig = inspect.signature(self.__new__)
bound = sig.bind_partial(type(self), *args, **kwargs)
for arg in sig.parameters:
if arg not in bound.arguments:
bound.arguments[arg] = getattr(self, arg)
return self.__new__(*bound.args, **bound.kwargs)
This will not work for subclasses defined in C, but at least we can show a nice
error about that. This will also not work if __new__ uses *args or **kwargs
instead of listing every property as its own argument.
(Another approach I can think of is patching properties on self, making a copy
of self via __reduce__, and reverting values on self back. This doesn't rely on
any signatures, but gets really dirty really quick.)
So I don't know if we want to implement this, or if returning base class from
replace() is a better choice.
----------
nosy: +eltoder, serhiy.storchaka
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue20371>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com