2

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?

3 Answers 3

2

You can have a parent class to hold the data:

class GridHolder:
    def __init__(self):
        self.grid = None


class A:

    def __init__(self, grid_holder: GridHolder):
        self.attrA = "attrA"
        self.grid_holder = grid_holder

    @property
    def grid(self):
        return self.grid_holder.grid

    @grid.setter
    def grid(self, value):
        self.grid_holder.grid = value


class B:
    def __init__(self, grid_holder: GridHolder):
        self.attrB = "attrB"
        self.grid_holder = grid_holder

    @property
    def grid(self):
        return self.grid_holder.grid

    @grid.setter
    def grid(self, value):
        self.grid_holder.grid = value

data_holder = GridHolder()

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]
Sign up to request clarification or add additional context in comments.

3 Comments

To be clear, You do not need to inherit from child in my example, I have just used it so I dont need to repeat the property and property setter code.
@cards Agreed, refactored. There are many ways to do it, I think this way is easy but I dont really like the idea of making a class just to hold a value.
@juanpa.arrivillaga I did do that but the question stated that the classes were separate. Ill edit it back in
1

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

8 Comments

In this code, every instance of class 'A' and 'B' will share the same data, where I believe OP wants different instances of 'A' and 'B' to not necessarily hold the same data
Indeed, this solution works most of the times, however I was looking for a solution that also allows for the possibility of not sharing the attribute.
What happened to: "contain the same value always,"?
But you just need a factory for the other instances: def make_plain_B(): return B(A()) and all the clients will never know.
@TomMcLean: In my code you have to specifically make a particular B refer to a particular A. You can have lots of As which don't share their data and with the factory above, you can have particular Bs refer to 'private' As.
|
0

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]

1 Comment

In this code, every instance of class 'A' and 'B' will share the same data because it is using a class variable, where I believe OP wants different instances of 'A' and 'B' to not necessarily hold the same data

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.