1

Alright, let's start with the code, because it's pretty explicit :

class c_1:
    def __init__(self):
        self.a = 5

class c_2:
    def __init__(self,other_obj):
        self.other = other_obj
        self.b = self.other.a

And the output:

obj_1 = c_1()
obj_2 = c_2(obj_1)
print(obj_2.b)
# Output is 5
obj_1.a = 8
print(obj_2.b)
# Output is still 5

This is the problem. I know the second call of obj_2.b should return 5, but I want it to return 8.

I think that what I actually want, is for the value of obj_1.a to be passed by reference for obj_2.b (this example is pretty simple, but in my actual code, there are more attributes from obj_1 that obj_2 uses.)

Is there a way, without calling another method, to automatically update obj_2.b when the value of obj_1.a gets changed ? Thank you.

3
  • 1
    Basically, the reason this can't be done is that Python variables are passed by value, not by references. Nor does Python have any language mechanism that allows you to declare variables which are references, like some other C-style languages. Commented May 5, 2019 at 4:26
  • 2
    You can circumvent this by encapsulating the values inside an object, and pass that around. Commented May 5, 2019 at 5:12
  • Does this answer your question? Accessing function as attribute in a Python class Commented Nov 27, 2023 at 5:24

2 Answers 2

2

It is possible, but your mileage may vary, depending on your use cases:

One approach, shown hereunder, is to implement a Var class that handles this for you; encapsulating the values inside an object circumvents the 'passing by value', and opens the 'values' to mutability. here is an incomplete (and brittle) example; there are quite a few corner cases to iron out to make it work smoothly, but to answer your question: yes, it is definitely possible:

Other approaches might use the inspect module, or metaclasses, or the implementation of callbacks.

tkinter in the python standard library uses specialized classes, and a callback approach.

class Var:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

    def __repr__(self):
        return str(self._value)


class IntVar(Var):

    def __iadd__(self, other: int):
        self._value = self._value + other
        return self.value


class c_1:
    def __init__(self):
        self._a = IntVar(5)

    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, value):
        self._a.value = value


class c_2:
    def __init__(self, other_obj):
        self.other = other_obj
        self.b = self.other.a


obj_1 = c_1()
obj_2 = c_2(obj_1)
print(obj_2.b)
obj_1.a = 8
print(obj_2.b)
obj_1.a += 2
print(obj_2.b)

Output:

5
8
10
Sign up to request clarification or add additional context in comments.

2 Comments

The first time I looked for solutions to my problem, I came across people using setter and getter and other decorations like that. Do you have any resource where I could learn more about how to use properties in Python ? EDIT : Nevermind, I think I finally got the gist of it. The goal is to make it so that, every time the attribute is "called", its value is updated. Is that correct ?
Yes, something like that; glad you got a deeper insight from my answer. :)
2

Is there a way, without calling another method, to automatically update obj_2.b when the value of obj_1.a gets changed ? Thank you

The answer is no.

The constructor of c_2 is setting the value of b to other_obj.a and the value of b is then fixed until you explicitly change its value again. Consider it as a normal (scalar) variable - once the value is set, it won't change until you explicitly assign a new value to it.

If you want to reference the value of a in c_2, you should always reference self.other.a as self.other is a reference to other_obj you passed to the constructor.

1 Comment

First off thank you. I don't quite understand your last statement, as it is already what I'm doing.

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.