1

I am working on optimization problems. As you know, optimization is an iterative process. Some sections are selected, and the weight of all sections is calculated.

I have code like this:

class Test:
    W = 0

    def __init__(self, l, A):
        self.l = l
        self.A = A
        Test.W += self.A * self.l

instance1 = Test(5, 10)
instance2 = Test(3, 7)
instance3 = Test(6, 13)

print(Test.W)

instance1.A = 20
instance2.A = 30
instance3.A = 40

print(Test.W)

At creation of instances 1-3, the program calculated 149 for W. It is correct. But if I change A values, the result is 149 again and again.

How can I update the class attribute W when I change A or l?

3
  • 1
    The __init__ code is not going to get rerun just because you changed an instance attribute. If you want to have side effects from setting an instance parameter, you should implement a Test.setA(new_A) method. Commented Dec 7, 2023 at 5:30
  • 1
    Consider, without the added complexity of classes, if I have the statements a = 1, x = a, a = 3, then print(x) will print 1 not 3. Assignment statements don't set up some on-going variable relationship. They get evaluated only when they are executed, and the Test.__init__() code only gets executed when the instances are being initialized. Commented Dec 7, 2023 at 5:34
  • This really shouldn't be a class attribute - that kind of design has a lot of awkward consequences if you want to solve two optimization problems, or if you want to write unit tests. Commented Dec 7, 2023 at 6:41

2 Answers 2

1

If you want modifications made to an instance attribute to effect the value of a class attribute, you can make the instance attribute a property and place the additional logics in its setter method instead:

class Test:
    W = 0

    def __init__(self, l, A):
        self.l = l
        self.A = A

    @property
    def A(self):
        try:
            return self._A
        except AttributeError:
            return 0

    @A.setter
    def A(self, value):
        Test.W += (value - self.A) * self.l
        self._A = value

so that:

instance1 = Test(5, 10)
instance2 = Test(3, 7)
instance3 = Test(6, 13)

print(Test.W)

instance1.A = 20
instance2.A = 30
instance3.A = 40

print(Test.W)

outputs:

149
430

Demo: https://ideone.com/pqUN4w

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

Comments

0

The issue is related to the fact that the class attribute W is calculated only once during the instantiation of the class. If you want to update the class attribute W when you change the values of A or l for an instance, you can create a method to recalculate and update W. You can use a class method for this purpose.

    class Test:
    W = 0

    def __init__(self, l, A):
        self.l = l
        self.A = A
        Test.calculate_and_update_W(self)

    @classmethod
    def calculate_and_update_W(cls, instance):
        cls.W += instance.A * instance.l

# Create instances
instance1 = Test(5, 10)
instance2 = Test(3, 7)
instance3 = Test(6, 13)

# Print initial value of Test.W
print(Test.W)

# Update A values for instances
instance1.A = 20
instance2.A = 30
instance3.A = 40

# Recalculate and update Test.W
Test.calculate_and_update_W(instance1)
Test.calculate_and_update_W(instance2)
Test.calculate_and_update_W(instance3)

# Print updated value of Test.W
print(Test.W)

In this version, I added a calculate_and_update_W class method, which takes an instance of the class as an argument and recalculates and updates the class attribute W accordingly. This method is then called during the initialization (init) to set the initial value and can be called again whenever you want to update W based on the current values of A and l.

Comments

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.