-
Notifications
You must be signed in to change notification settings - Fork 50
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
Improve object copying #535
Comments
Sounds like a good idea to me! Looks like this is almost entirely supported already, apart from copying the data. Most constructors already correctly handle the first parameter being an instance of itself, but the data is shared rather than copied. This is in line with how regular (not deep) copying is intended to work in python, as per https://docs.python.org/3/library/copy.html, and means your example code already works as it should for most orix objects! If the constructor instead should deepcopy (which makes more sense, I think), then it is not too much work to add e.g. .copy() to the numpy arrays. We could also get more control over the copy behaviour by overriding the dunder methods for copy and deepcopy, instead of changing any existing code. |
Something like: class A:
def __init__(self, arg_1 = None):
if isinstance(arg_1, A):
A.__init__(
self,
arg_1.arg_1.copy(),
)
return
self.arg_1 = arg_1
... feels like a decent design too, and gives control over copying by how we pass the parameters to the recursive constructor call. A more complete example: import numpy as np
class Foo:
def __init__(self, a: np.ndarray = None, b: np.ndarray = None) -> None:
if isinstance(a, Foo):
Foo.__init__(self, a.a.copy(), a.b.copy())
return
self.a = a
self.b = b
class Bar(Foo):
def __init__(self, a: np.ndarray = None, b: np.ndarray = None, c: np.ndarray = None) -> None:
if isinstance(a, Bar):
Bar.__init__(self, a.a.copy(), a.b.copy(), a.c.copy())
return
super().__init__(a, b)
self.c = c
# Check that the copying works
test_1 = Foo(np.random.random(3), np.random.random(3))
test_2 = Foo(test_1)
assert test_1 is not test_2
assert test_1.a is not test_2.a
assert np.array_equal(test_1.a, test_2.a)
# Check that copying works for subclasses
test_3 = Bar(np.random.random(3), np.random.random(3), np.random.random(4))
test_4 = Bar(test_3)
assert test_3 is not test_4
assert test_3.c is not test_4.c
assert np.array_equal(test_3.c, test_4.c)
# Check that subclasses can be cast to parent
test_5 = Foo(test_3)
assert test_3 is not test_5
assert test_3.a is not test_5.a
assert np.array_equal(test_3.a, test_5.a)
assert not hasattr(test_5, "c") and not isinstance(test_5, Bar) |
Looking beyond #533, I think it may be better to avoid
deepcopy()
altogether and rather add acopy()
method, like thisWe can update the creation method to allow another instance as the first parameter, and only copy the things we need.
We can deprecate
deepcopy()
in favor ofcopy()
.Benefits:
Vector3d(Vector3d)
orVector3d.copy()
What do you think, @viljarjf?
Originally posted by @hakonanes in #533 (comment)
@CSSFrancis?
The text was updated successfully, but these errors were encountered: