1

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.

6
  • 3
    __init__ is a @classmethod??? Commented Mar 10, 2017 at 13:30
  • @WillemVanOnsem good point! that's the answer BTW. A classmethod shouldn't be used, remove the decorators. Commented Mar 10, 2017 at 13:30
  • or maybe it's different in pythan. Commented Mar 10, 2017 at 13:31
  • if i remove @classmethod from init, it is giving error as "AttributeError: type object 'TestClass' has no attribute 'val'" Commented Mar 10, 2017 at 13:32
  • @Jai you should equally remove it from value, since val is now bound to the instance Commented Mar 10, 2017 at 13:33

2 Answers 2

7

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.

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

Comments

2

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

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.