accessing superclass methods from subclass

Chris Rebert clp2 at rebertia.com
Sat May 8 23:44:59 EDT 2010


> On May 8, 7:05 pm, Chris Rebert <c... at rebertia.com> wrote:
>> On Sat, May 8, 2010 at 4:50 PM, ben <thomasstr... at gmail.com> wrote:
>> > Why doesn't this work:
>>
>> > class C1:
>> >    def f1(self):
>> >        print("f1")
>>
>> > class C2(C1):
>> >    f1()
>>
>> > It throws this error:
>>
>> > Traceback (most recent call last):
>> >  File "./c1.py", line 7, in <module>
>> >    class C2(C1):
>> >  File "./c1.py", line 8, in C2
>> >    f1()
>> > NameError: name 'f1' is not defined
>>
>> > f1() is an attribute of class C1, C2 inherits C1, so why can't it see
>> > it?
>>
>> The way classes work in Python, C2 isn't actually created until after
>> its body suite has been executed, so that's why Python can't find f1.
>>
>> Additionally, it makes no sense to call an *instance* method such as
>> f1() in a class context. Or in Java-speak: you can't call a non-static
>> method in a static context.
On Sat, May 8, 2010 at 8:24 PM, ben <thomasstruth at gmail.com> wrote:
> Ok, thanks for the info.
>
> What would be a better way to do this?  What I'm trying to do is treat
> things in a reasonable OOP manner (all fairly new to me, esp. in
> Python).  Here's a made-up example with a little more context.  Let's
> say you're making a drawing program that can draw various shapes.  So
> in the interest of not repeating oneself, I want a class Shape that
> handles everything that shapes have, such as a color, and a location.
> Then I can subclass Shape to create Square, which has code specific to
> drawing a square (e.g. 4 equal sides).  So, like this:
>
> class Shape:
>
>    x = 0
>    y = 0
>
>    def setColor(self,color):
>        self.color = color
>
>    def setLocation(self,x,y):
>        self.x = x
>        self.y = y
>
>    def getLocation(self):
>        return [self.x,self.y]
>
> class Square(Shape):
>
>    size = 0
>
>    def __init__(self,size):
>        self.size = size
>
>    def draw(self):
>        location = getLocation()
>        # code to draw shape from location[0],location[1] at size size
>        # etc...
>
> It seems to me that you would want the location code handled in the
> Shape class so that I'm not rewriting it for Circle, Triangle, etc.,
> but I'm not allowed to call any of those methods from the subclass.  I
> must be thinking of this in the wrong way.  Help?

Your code suggests you need to read a tutorial on Python's
object-oriented features. The relevant part of Python's official
tutorial is http://docs.python.org/tutorial/classes.html

For starters, Python is not Java and getters/setters are not usually
necessary nor Pythonic; see
http://dirtsimple.org/2004/12/python-is-not-java.html
Secondly, Python does not have instance variable declarations; doing
`x = 0` at the class-level creates a static/class variable, it *does
not* declare an instance variable.
Thirdly, to call an instance method such as getLocation, you need to
specify the receiver, i.e. `self.getLocation()`, not merely
`getLocation()`

Here is how I would rewrite your example:

class Shape(object):
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    @property
    def location(self):
        return (self.x, self.y)

    @location.setter
    def location(self, val):
       self.x, self.y = val

class Square(Shape):
   def __init__(self,size):
       super(Square, self).__init__()
       self.size = size

   def draw(self):
       x, y = self.location
       # code to draw shape from location[0],location[1] at size size
       # etc...


This uses some minor magic involving property(), see
http://docs.python.org/library/functions.html#property for how that
works.

Cheers,
Chris
--
http://blog.rebertia.com



More information about the Python-list mailing list