Jai
Jai

Reputation: 1332

Issue with class variable in Python

I am new to python.I was doing following code and I met an undesired outcome. Please look onto my code and let me know what am I doing wrong:

class TestClass(object):
  @classmethod
  def __init__(self, val):
    self.val = val

  @classmethod
  def value(self):
    return self.val

def Test():
  a = TestClass(9)
  b = TestClass(8)
  c = TestClass(7)
  print(a.value(), b.value(), c.value())

expecting output as

9 8 7

but getting output as

7 7 7

what is wrong with my code.

Upvotes: 1

Views: 61

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476557

You have attached @classmethod to the __init__ function. As a result, if you call the __init__ (something you do at construction), self will not reference to the object you are about to construct, but to the class, so TestClass. Therefore there is only one value: attached to TestClass.

So TestClass(3) will be equivalent to something like TestClass.__init__(TestClass,3)...

You can solve the issue by removing the @classmethod decorator:

class TestClass(object):

  def __init__(self, val): # no @classmethod
    self.val = val

  def value(self): # no @classmethod
    return self.val

def Test():
  a = TestClass(9)
  b = TestClass(8)
  c = TestClass(7)
  print(a.value(), b.value(), c.value())

It is actually rather weird to use a @classmethod on an __init__ method. If you want to add attributes to the class, you can use type(..). So:

@classmethod
def __init__(cls, val):
    cls.val = val

Is equivalent to:

def __init__(self, val):
    type(self).val = val

Upvotes: 2

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160377

Setting __init__ as a classmethod means you're actually passing the class to __init__ and self.val is actually set as a class variable, not an instance variable.

The final "initialization" you perform will override all the other values you've set.

Removing the @classmethods fixes the issue.

Upvotes: 7

Related Questions