Is it possible in Python to have two objects, each of them an instance of a different class, that always share the same value for a particular attribute?
For instance, suppose the following code:
class A():
def __init__(self):
self.attrA = "attrA"
self.grid = None
def init_grid(self, x):
self.grid = x
class B():
def __init__(self):
self.attrB = "attrB"
self.grid = None
def init_grid_as_preexisting(self, pre_grid):
self.grid = pre_grid
a = A()
a.init_grid([1,2,3])
b = B()
b.init_grid_as_preexisting(a.grid)
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [1, 2, 3] [1, 2, 3]
a.grid = [4,5,6]
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [4, 5, 6] [1, 2, 3]
b.grid = [7,8,9]
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [4, 5, 6] [7, 8, 9]
Here my goal would be for a.grid
and b.grid
to contain the same value always, regardless of whether one is initialized from the other or which one is modified; the desired output would be then:
a.grid, b.grid = [1, 2, 3] [1, 2, 3]
a.grid, b.grid = [4, 5, 6] [4, 5, 6]
a.grid, b.grid = [7, 8, 9] [7, 8, 9]
In this question it is suggested to use a base class containing a class attribute, and use a static method to modify the desired shared attribute. I would rather not use this solution as I don't want to have this attribute shared among all instances always, only when it is strictly desired. From this other question, I guess I could use the Mutable Default Argument property to have a shared value for a given parameter, but again, I don't always want the parameter to be shared.
In short, is it possible to have two objects, each an instance of two different classes, to have a shared parameter?
CodePudding user response:
You can have a parent class to hold the data:
class Parent:
def __init__(self):
self.grid = None
class Child:
def __init__(self, parent: Parent):
self.parent = parent
@property
def grid(self):
return self.parent.grid
@grid.setter
def grid(self, value):
self.parent.grid = value
class A(Child):
def __init__(self, parent: Parent):
super().__init__(parent)
self.attrA = "attrA"
def init_grid(self, x):
self.grid = x
class B(Child):
def __init__(self, parent: Parent):
super().__init__(parent)
self.attrB = "attrB"
def init_grid_as_preexisting(self, pre_grid):
self.grid = pre_grid
data_holder = Parent()
a = A(data_holder)
a.grid = [1, 2, 3]
b = B(data_holder)
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [1, 2, 3] [1, 2, 3]
a.grid = [4, 5, 6]
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [4, 5, 6] [1, 2, 3]
b.grid = [7, 8, 9]
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [4, 5, 6] [7, 8, 9]
Output:
a.grid, b.grid = [1, 2, 3] [1, 2, 3]
a.grid, b.grid = [4, 5, 6] [4, 5, 6]
a.grid, b.grid = [7, 8, 9] [7, 8, 9]
CodePudding user response:
You can have the B
instance refer to the A
instance and use properties to refer to the grid
attribute:
class A():
def __init__(self):
self.attrA = "attrA"
self.grid = None
def init_grid(self, x):
self.grid = x
class B():
def __init__(self, a):
self.attrB = "attrB"
self.a = a
@property
def grid(self):
return self.a.grid
@grid.setter
def grid(self, value):
self.a.grid = value
a = A()
a.init_grid([1,2,3])
b = B(a)
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [1, 2, 3] [1, 2, 3]
a.grid = [4,5,6]
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [4, 5, 6] [1, 2, 3]
b.grid = [7,8,9]
print("a.grid, b.grid = ", a.grid, b.grid)
# OUT: a.grid, b.grid = [4, 5, 6] [7, 8, 9]
Output as requested
CodePudding user response:
You could make use of a class variable
and using .grid
as property, A
and B
inherit from grid
the properties only:
class grid:
_grid = None
@property
def grid(self):
return grid._grid
@grid.setter
def grid(self, value):
grid._grid = value
class A(grid):
def __init__(self):
self.attrA = "attrA"
class B(grid):
def __init__(self):
self.attrB = "attrB"
a = A()
a.grid = [1, 2, 3]
b = B()
print("a.grid, b.grid = ", a.grid, b.grid)
a.grid = [4, 5, 6]
print("a.grid, b.grid = ", a.grid, b.grid)
b.grid = [7, 8, 9]
print("a.grid, b.grid = ", a.grid, b.grid)
Out:
a.grid, b.grid = [1, 2, 3] [1, 2, 3]
a.grid, b.grid = [4, 5, 6] [4, 5, 6]
a.grid, b.grid = [7, 8, 9] [7, 8, 9]