4

So, i'm trying to learn python and every time i post a question here it feels like giving in...

I'm trying to make my own class of turtle.Turtle.

    import turtle
class TurtleGTX(turtle.Turtle):
    """My own version of turtle"""
    def __init__(self):
        pass

my_turtle = TurtleGTX()
my_turtle.forward(10)

Gives the Traceback: AttributeError: 'TurtleGTX' object has no attribute '_position'. Which I then learn is a "private vairable" which according to the offical python tutorial i can mangle/override in my subclass TurtleGTX. How to do this with a program as large as turtle seems rather difficult and implies i'm missing a simpler solution to the problem. In the end i learned and that was the point but i would still like to run it by the community to see if there is a elegant way to create a subclass of turtle.Turtle. (The next step is to have your turtle behave different then the standard turtle)

So a comment below made me think that maybe i could do this:

import turtle
class TurtleGTX(turtle.Turtle):
    """My own version of turtle"""


my_turtle = TurtleGTX()
my_turtle.forward(100)

which actual runs! Now i'm going to see where that leads me... something tells me that i might have gone 1 step forward two step back as this means i won't be able to initialize anything on my subclass...

unor
  • 87,575
  • 24
  • 195
  • 335
Drew Verlee
  • 1,772
  • 5
  • 20
  • 30

3 Answers3

8

Rounding up Ignacio's answer and orokusaki's comment you probably should write something like

import turtle
class TurtleGTX(turtle.Turtle):
    """My own version of turtle"""
    def __init__(self,*args,**kwargs):
        super(TurtleGTX,self).__init__(*args,**kwargs)
        print("Time for my GTX turtle!")

my_turtle = TurtleGTX()
my_turtle.forward(100)
Odomontois
  • 15,341
  • 2
  • 35
  • 70
  • Thanks for the help, I might have mis-understood the question the tutorial was asking as they never introduced super, *args or **kwargs... – Drew Verlee Feb 25 '12 at 14:39
2

If you redefine a method (such as __init__()) in a child class then it is your responsibility to call the parent's method in order to have the parent's behavior respected.

Ignacio Vazquez-Abrams
  • 740,318
  • 145
  • 1,296
  • 1,325
  • Also note, your __init__ needs to accept the same args, kwargs as the parent and you need to call the super() init with the args, kwargs, unless you intend to rewrite the interface. – orokusaki Feb 25 '12 at 05:26
0

It's a tempting pattern to subclass Turtle and add custom functionality, say, turtle.jump(). But I've had limited success with this pattern and caution against it in most cases.

Calling t = Turtle() (including subclasses of Turtle) registers the object with the turtle module's internal list of turtles. This list has _update() called on it per frame if you don't disable the internal update loop with turtle.tracer(0). This internal turtle isn't likely to get garbage collected as your subclass might expect, and we shouldn't hook into private methods denoted by the leading underscore. Even if we can, it gets messy quickly; in addition to the update/draw internals they're hooked into, Turtle has many properties and methods that can easily name clash your custom methods.

I suggest one of a few alternative patterns that are somewhat use-case specific:

  • If you don't mind the turtles not being garbage collected (are making a fixed amount that you plan to keep around), you could allocate instances of a custom class, each of which has an internal self.turtle = Turtle() instance that is manipulated in the normal way from the wrapper.
  • Instead of classes, you could make Turtle instances and pass them to functions that cause them to take an action in a C-style imperative manner: def jump(turtle, height): ....
  • If you plan to create particles of some sort that are created and destroyed relatively frequently and you just need a turtle to render them, you might store the particles' internal representations and physics properties with a reference to a single "pen" turtle. When drawing is needed, tracing is disabled and the turtle is moved from one position to the next among all shared particles, drawing as needed.

That said, I'd be eager to see a useful case of the subclassing pattern if anyone has one.

ggorlen
  • 33,459
  • 6
  • 59
  • 67