11

I have this code:

class Yes:
    def __init__(self):
        self.a=1

    def yes(self):
        if self.a==1:
            print "Yes"
        else:
            print "No, but yes"

class No(Yes):
    def no(self):
        if self.a==1:
            print "No"
        else:
            print "Yes, but no"
        self.a-=1 #Note this line

Now, while running:

Yes().yes()
No().no()
Yes().yes()
No().no()

I want it to print out:

Yes
No
No, but yes
Yes, but no

It gives me:

Yes
No
Yes
No

I know the reason is that I'm only changing the value of self.a in the No class. Is there any way to change it in the Yes class while still in the No class (like if there was something that I could plug in in place of the self.a-=1 that would work)?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
user2154113
  • 401
  • 1
  • 6
  • 12
  • you can write a setter method in the class , and call it from the other class – karthikr Apr 03 '13 at 14:44
  • I tried that, it keeps calling back self.a=1 – user2154113 Apr 03 '13 at 14:47
  • 1
    Also see http://stackoverflow.com/questions/68645/static-class-variables-in-python – Michal Čihař Apr 03 '13 at 14:54
  • 1
    @MichalČihař in particular [this answer](https://stackoverflow.com/a/69067/673991) gets to the heart of the problem here: **you cannot set a class variable through `self`**. You must use the _class name_ instead. The confusion comes from being able to _get_ a class variable through `self`. – Bob Stein Nov 17 '20 at 16:09

2 Answers2

20

I'm not sure what possible use you have for this, but...

You want to manipulate a class variable, but you keep addressing instance variables. If you want a class variable, use a class variable!

class Yes:
    a = 1 # initialize class var.
    def __init__(self):
        self.a = 1 # point of this is what?

    def yes(self):
        if Yes.a==1: # check class var
            print "Yes"
        else:
            print "No, but yes"

class No(Yes):

    def no(self):
        if Yes.a==1: # check class var
            print "No"
        else:
            print "Yes, but no"
        Yes.a-=1 # alter class var
Francis Avila
  • 31,233
  • 6
  • 58
  • 96
  • I was using it as an example for something else I was trying to do, thank you – user2154113 Apr 03 '13 at 14:59
  • 3
    Using class vars like this seems like code smell. Are you sure what you are doing can't be accomplished some other way? – Francis Avila Apr 03 '13 at 15:07
  • 1
    @FrancisAvila I think you were thrown off by his setting `a` in the constructor. He was merely trying to demonstrate a method changing the value of a class variable. The answer to that would have been `Yes.a = 1`. [Moral of the story](https://stackoverflow.com/a/69067/673991), you can get a class variable through self, but you can't set it that way. – Bob Stein Nov 17 '20 at 16:12
  • @BobStein Thanks for pointing out that distinction. still bugs me! – Sujay Phadke Jul 30 '21 at 09:53
  • @SujayPhadke it's a recurring trauma for me too. Perennial Python pitfall: attempting to **set a class property via `self`**. – Bob Stein Jul 30 '21 at 14:02
  • @BobStein Wonder why python allows it. Ambiguity is not Pythonic. – Sujay Phadke Jul 30 '21 at 14:30
2

It appears what you want to use is a static variable rather than an instance variable. A static variable is shared between all the instances of the class.

class Yes:
    a = 1
    def __init__(self):
        pass

    def yes(self):
        if Yes.a==1:
            print "Yes"
        else:
            print "No, but yes"

class No(Yes):

    def no(self):
        if Yes.a==1:
            print "No"
        else:
            print "Yes, but no"
        Yes.a-=1 #Note this line

Yes().yes()
No().no()
Yes().yes()
No().no()

Will output:

Yes
No
No, but yes
Yes, but no
Jesse Vogt
  • 16,229
  • 16
  • 59
  • 72
  • 1
    This is not a static variable, it's a class variable. If it changes, it changes for the class. – Mayou36 Jun 27 '21 at 18:43