2025, Nov 09 19:00
Python turtle: Subclassing Screen raises 'code must be code, not str' - fix with _Screen or composition
Learn why Python turtle Screen can't be subclassed and triggers TypeError: 'code' must be code, not str. See fixes via _Screen or composition and best practice
Subclassing turtle.Screen throws “TypeError: function() argument 'code' must be code, not str” — and it’s not about your game logic. The root cause is simpler: in turtle, Screen is not a class you can inherit from. It’s a function that returns an instance of the internal implementation class. If you inherit from a function, Python rightfully complains.
Problem setup
Consider a minimalized version of a Pong-like scaffold split across two files. The failing part is the inheritance from Screen.
This is the launcher:
from arena import Stage
from paddle import Paddle
from orb import Orb
from tally import Tally
ARENA_W = 600
ARENA_H = 500
PAD_SIZE = 50
field = Stage(ARENA_W, ARENA_H, pad_user, pad_cpu, tally_user, tally_cpu, orb)
pad_user = Paddle(ARENA_W, ARENA_H, PAD_SIZE)
pad_cpu = Paddle(ARENA_W, ARENA_H, PAD_SIZE)
tally_user = Tally(ARENA_W, ARENA_H)
tally_cpu = Tally(ARENA_W, ARENA_H)
orb = Orb()
running = True
while running:
field.bat_orb_touch()
And here is the screen wrapper:
from turtle import Screen, Turtle
class Stage(Screen):
def __init__(self, w, h, pad_u, pad_c, sc_u, sc_c, orb):
super().__init__()
self.w = w
self.h = h
self.pad_u = pad_u
self.pad_c = pad_c
self.sc_u = sc_u
self.sc_c = sc_c
self.orb = orb
self.bgcolor("black")
self.screensize(w, h)
draw_center_line()
def draw_center_line(self):
center = Turtle()
center.pensize(20)
center.pencolor("white")
center.penup()
center.goto(0, self.h-10)
center.setheading(270)
center.pendown()
for step in range(self.h/(2*10)):
center.forward(10)
if cen_line.pencolor() == 'white':
cen_line.pencolor('black')
else:
cen_line.pencolor('white')
def bat_orb_touch(self, bat):
return all([abs(orb.xcor()-bat.xcor()) < 10, abs(orb.ycor()-bat.ycor()) < 15])
Why it fails
The error is triggered at the class definition line where Stage tries to inherit from Screen. In turtle, Screen is not a class; it’s a function. That function constructs and returns an instance of the underlying class. Attempting class Stage(Screen): in this situation fails with the exact error you see because Python expects a class (or compatible type) in the bases, not a function.
The internal class that actually implements the window is named _Screen. That’s the type you would subclass if you truly need inheritance semantics.
Fix
Use the internal class that backs Screen. The inheritance must target _Screen, not Screen.
from turtle import _Screen, Turtle
class Stage(_Screen):
def __init__(self, w, h, pad_u, pad_c, sc_u, sc_c, orb):
super().__init__()
self.w = w
self.h = h
self.pad_u = pad_u
self.pad_c = pad_c
self.sc_u = sc_u
self.sc_c = sc_c
self.orb = orb
self.bgcolor("black")
self.screensize(w, h)
draw_center_line()
def draw_center_line(self):
center = Turtle()
center.pensize(20)
center.pencolor("white")
center.penup()
center.goto(0, self.h-10)
center.setheading(270)
center.pendown()
for step in range(self.h/(2*10)):
center.forward(10)
if cen_line.pencolor() == 'white':
cen_line.pencolor('black')
else:
cen_line.pencolor('white')
def bat_orb_touch(self, bat):
return all([abs(orb.xcor()-bat.xcor()) < 10, abs(orb.ycor()-bat.ycor()) < 15])
This change addresses the specific type error caused by inheriting from a function. The rest of the logic remains as is.
Why this detail matters
turtle exposes Screen as a factory-style entry point, while the true implementation class is _Screen. Knowing this prevents a class of confusing inheritance-time errors. There is also a broader design takeaway that’s often recommended in this context: prefer composition over inheritance for turtle constructs — a game container has-a Screen rather than is-a Screen.
Takeaways
If a base “class” produces a TypeError at the class statement itself, verify what you are inheriting from. Checking the type of the symbol before use is a quick sanity test. If you decide to stay with inheritance for your window wrapper, inherit from _Screen. If you prefer to keep to the public-facing surface, build your system around a Screen instance and compose your objects around it. Finally, when isolating an error like this, reduce to a minimal reproducible example to locate the failure point quickly and avoid chasing unrelated parts of the code.