Long time reader, first time asker. Anyway, Here’s the code I’m working with:
class Person(object):
def __init__(self, s):
self.name = s
self.secret = 'I HAVE THE COOKIES'
@classmethod
def shout(self):
print self.name.upper()
class Kid(Person):
def __init__(self, s):
super(Kid,self).__init__(s)
self.age = 12
b = Person('Bob')
k = Kid('Bobby')
print b.name
print k.name
print k.age
print k.secret
k.shout()
Which results in this output and error:
Bob
Bobby
12
I HAVE THE COOKIES
Traceback (most recent call last):
File "a.py", line 22, in <module>
k.shout()
File "a.py", line 8, in shout
print self.name.upper()
AttributeError: type object 'Kid' has no attribute 'name'
I assumed that Kid would be able to use the Person’s shout method substituting its (the kid’s) “self” for parent (where the method lives). Apparently, that’s not the case. I know I could declare name outside of init, but that’s both unable to accomodate inputted data and a no-no. Another alternative would be to redefine shout for every child of Person, but that’s a lot of repeated code that I’m trying to avoid.
Thanks very much in advance!
The issue is that
@classmethodis a method on a class. It does not have access to an instance’s attributes. Specifically the method is actually passed the class object, thusselfis misnamed. You should really callshout‘s argumentcls. If you remove the@classmethodthen this would all make sense and your code would work as expected.As it is, you can think of
k.shout()as equivalent toKid.shout().