-1

Consider the following minimal example for my question:

class MyClass:
    a = False
    b = 0
    if a:
        b = 1

MCinst = MyClass()

Here MCinst has two attributes, MCinst.a and MCinst.b with default values False and 0 respectively. What I was trying to achieve with the if statement, is that the value of MCinst.b would automatically switch to 1 when I set MCinst.a = True. But this obviously does not work as intended, since the value of MCinst.b stays 0.

I know that I could remove the if statement and simply modify b from the outside, in the same way in which I modified a. But I am still curious if there is a way to make work what I wanted—i.e. to have an attribute of an instance change automatically when I change another attribute of the same instance.

Britzel
  • 205
  • 3
  • 8
  • 1
    Those are *class* attributes, but if you do actually want a class property see https://stackoverflow.com/q/128573/3001761. – jonrsharpe Oct 21 '20 at 18:47

1 Answers1

1
class MyClass:
    a = False
    b = 0     

    def __setattr__(self, key, value):
        if key == 'a':
            setattr(self, 'b', 1)
        super().__setattr__(key, value)

If you actually want to change the class attribute, you can use

setattr(self.__class__, 'b', 1)
Roeik
  • 91
  • 3
  • It works! Thanks a lot Roeik. Allow me some followup questions: (1) So __setattr__ gets automatically called whenever an attribute is set? (2) What is the purpose of the super().... line? (3) What is the difference between setting a class attribute and doing what you did? (Sorry, I am quite new to Obj. Oriented programming and wording.) – Britzel Oct 21 '20 at 19:47
  • (1) Yes. (2) the base class of _ MyClass_ is object. object implements __setattr__, so by calling super().__setatrr__() we delegate the setting of the value to object. (3) class attributes are not bounded to an instance, so if for example you change them, all future instances will get the new value. – Roeik Oct 21 '20 at 20:07
  • Sorry, may I please bug you once more? I found a problem with the solution you gave, which is due to my faulty explanation. What you do changes the value of `instance.b` to `1` whenever `instance.a` is set. What I would need is that `instance.b` is set to `0`or `1` whenever `instance.a` is set to `False` or `True` respectively. I tried to do that by modifying your code, and additionally checking the value of `self.a` inside of `__setattr__()`. However `self.a` prints as `False`, regardless of which value I set `instance.a` to. Would you have an idea how to do it perhaps? – Britzel Oct 22 '20 at 09:36
  • So it seems that whatever happens in `__setattr__()` is executed before the attribute is actually set. At least this is what I think is going on. – Britzel Oct 22 '20 at 09:54