【初心者向け】Python Turtleグラフィックスの基本と応用
Pythonの「turtle」モジュールとは
「turtle」モジュールは、Pythonに標準で搭載されているグラフィック描画モジュールです。画面上に「タートル」(カメ)と呼ばれるカーソルを動かすことで、線や図形を描画することができます。元々は教育用プログラミング言語であるLogoから派生しており、プログラミング初心者でも視覚的にコードの動作を理解しやすいのが特徴です。
「Public classes」(公開クラス)とは
Pythonのモジュールにおいて「公開クラス」とは、そのモジュールを利用するプログラマーが直接インスタンス化して使用することを意図されたクラスのことです。つまり、「turtle」モジュールを使う際に、自分でオブジェクトを作成し、そのオブジェクトのメソッド(関数)を呼び出して描画を行うための「設計図」のようなものです。
「turtle」モジュールにおける主要な公開クラスは以下の2つです。
turtle.Turtle
クラスturtle.Screen
クラス
これらのクラスを理解することで、より柔軟でオブジェクト指向的なタートルグラフィックスのプログラミングが可能になります。
turtle.Turtle クラス
turtle.Turtle
クラスは、画面上で実際に絵を描く「タートル」そのものを表します。このクラスのインスタンス(オブジェクト)を作成することで、複数のタートルを同時に動かしたり、それぞれ異なる設定(色、形、線の太さなど)を持たせたりすることができます。
使い方
import turtle
# Turtleオブジェクトを作成する
my_turtle = turtle.Turtle()
# 作成したタートルを使って描画する
my_turtle.forward(100) # 100ピクセル前進
my_turtle.right(90) # 右に90度回転
my_turtle.color("red") # 色を赤にする
my_turtle.circle(50) # 半径50の円を描く
turtle.Turtle
クラスには、以下のような多くのメソッドがあります。
- タートルの状態
shape()
,shapesize()
,hideturtle()
,showturtle()
など - 描画の制御
circle()
,dot()
,stamp()
,begin_fill()
,end_fill()
など - ペンの制御
penup()
,pendown()
,pensize()
,pencolor()
など - 動きの制御
forward()
,backward()
,right()
,left()
,goto()
,setheading()
など
turtle.Screen クラス
turtle.Screen
クラスは、タートルが絵を描く「画面」または「キャンバス」全体を表します。背景色や背景画像の設定、ウィンドウのサイズ調整、イベント処理(クリックやキー入力など)の設定など、画面全体に関する操作を行うために使用されます。
使い方
import turtle
# Screenオブジェクトを取得する (通常はシングルトンなので直接インスタンス化するより取得することが多い)
my_screen = turtle.Screen()
# 画面の設定をする
my_screen.bgcolor("lightblue") # 背景色を水色にする
my_screen.title("私のタートルグラフィックス") # ウィンドウのタイトルを設定
my_screen.setup(width=600, height=400) # ウィンドウのサイズを設定
# イベント処理を設定する例
# my_screen.onclick(some_function) # クリック時の処理を設定
turtle.Screen
クラスの主なメソッドには以下のようなものがあります。
- ウィンドウ制御
bye()
,exitonclick()
など - イベント処理
onclick()
,onkey()
,listen()
など - アニメーション制御
tracer()
,delay()
,update()
など - 画面設定
bgcolor()
,bgpic()
,setup()
,screensize()
,title()
など
turtle.Turtle
や turtle.Screen
のような公開クラスを使うことで、タートルグラフィックスのプログラミングをオブジェクト指向的に行うことができます。これにより、以下のような利点があります。
- 再利用性
特定の描画パターンを持つカスタムタートルクラスを作成し、それを再利用することができます。 - コードの整理
画面に関する設定とタートル自身の描画操作をそれぞれのクラスのメソッドとして分離できるため、コードが読みやすくなります。 - 複数のタートルの管理
複数のturtle.Turtle
オブジェクトを作成し、それぞれを独立して制御できるため、複雑なアニメーションや図形を描画しやすくなります。
初心者向けの簡単なプログラムでは、from turtle import *
のようにモジュール全体をインポートして、forward()
, circle()
などの関数を直接呼び出す形式がよく使われます。これは、モジュールが自動的にシングルトンな Turtle
オブジェクトと Screen
オブジェクトを作成し、そのメソッドをグローバルな関数として公開しているためです。しかし、より高度な描画や複数のタートルを扱う場合は、上記のような公開クラスを明示的にインスタンス化して使用することが推奨されます。
Python turtle
モジュールの公開クラスにおけるよくあるエラーとトラブルシューティング
turtle
モジュールは初心者にも扱いやすいですが、いくつかの共通の落とし穴があります。ここでは、主要なエラーとその解決策を見ていきましょう。
AttributeError: module 'turtle' has no attribute 'Turtle' または AttributeError: module 'turtle' has no attribute 'Screen'
原因
このエラーは、Pythonがturtle
モジュールの中にTurtle
やScreen
という名前のクラスを見つけられない場合に発生します。最も一般的な原因は以下のいずれかです。
- 大文字・小文字の誤り
クラス名は大文字で始まる必要があります(例:turtle.Turtle()
、turtle.Screen()
)。turtle.turtle()
やturtle.screen()
のように小文字で記述すると、Pythonはそれらを認識できません。 - ファイル名の衝突
実行しているPythonスクリプトの名前がturtle.py
である場合、Pythonは標準ライブラリのturtle
モジュールではなく、あなたの作成したturtle.py
ファイルをインポートしようとします。その結果、あなたのファイルにはTurtle
やScreen
クラスが定義されていないため、このエラーが発生します。
トラブルシューティング
- 大文字・小文字の確認
コード内でTurtle
やScreen
を正しく大文字で記述しているか確認してください。 - ファイル名の変更
現在実行しているスクリプトのファイル名をmy_turtle_drawing.py
など、turtle.py
以外の名前に変更してください。
NameError: name 'forward' is not defined など
原因
このエラーは、turtle
モジュールから特定の関数(例: forward()
, right()
, circle()
)を直接呼び出そうとしたときに発生します。これは、関数が特定のタートルオブジェクトのメソッドとして存在するためです。
使い方を間違えている例
import turtle
forward(100) # エラー!
トラブルシューティング
- タートルオブジェクトの作成と使用
turtle.Turtle()
でタートルオブジェクトを作成し、そのオブジェクトを介してメソッドを呼び出す必要があります。
import turtle
my_turtle = turtle.Turtle() # Turtleオブジェクトを作成
my_turtle.forward(100) # my_turtleオブジェクトのメソッドを呼び出す
- from turtle import * の使用(注意点あり)
from turtle import *
を使うと、turtle
モジュールのすべての関数やクラスがグローバル名前空間にインポートされるため、forward()
のように直接関数を呼び出すことができるようになります。
from turtle import * # 全ての関数をインポート
forward(100) # この場合はエラーにならない
right(90)
注意点
from module import *
は、名前の衝突を引き起こす可能性があるため、大規模なプロジェクトや他のモジュールと組み合わせる場合には推奨されません。一般的には、import turtle
として、turtle.Turtle()
のように明示的にアクセスする方が良いプラクティスとされています。
ウィンドウが表示されない、またはすぐに閉じてしまう
原因
プログラムが終了すると、turtle
のグラフィックウィンドウも自動的に閉じられてしまいます。描画が完了してもウィンドウがすぐに消えてしまう場合、これはプログラムが終了したことを意味します。
トラブルシューティング
- turtle.done() または screen.exitonclick() を追加
プログラムの最後にturtle.done()
またはturtle.Screen().exitonclick()
(または、既にScreen
オブジェクトを取得している場合はscreen.exitonclick()
)を呼び出すことで、ウィンドウを閉じずに表示し続け、ユーザーがクリックするまで待機させることができます。
import turtle
my_turtle = turtle.Turtle()
my_turtle.forward(100)
turtle.done() # または screen.exitonclick()
# これがないと、描画後にウィンドウがすぐに閉じてしまう
TypeError: invalid argument または ValueError
原因
turtle
のメソッドに、期待される型や範囲外の引数を渡した場合に発生します。例えば、数値が期待される引数に文字列を渡したり、色名として無効な文字列を渡したりするケースです。
例
my_turtle.forward("百") # 数値ではなく文字列を渡しているため TypeError
my_turtle.color("変な色") # 無効な色名のため TurtleGraphicsError (ValueErrorの一種)
トラブルシューティング
- 数値はクォーテーションで囲まない
forward(100)
のように数値を直接渡すようにし、forward("100")
のように文字列として渡さないように注意してください。 - 引数の型と値の確認
各メソッドのドキュメントや例を参照し、引数として適切な型(整数、浮動小数点数、文字列など)と有効な値(色名、角度など)を渡しているか確認してください。
ModuleNotFoundError: No module named 'turtle'
原因
ごく稀ですが、Pythonのインストールが不完全だったり、環境設定に問題があったりする場合に発生することがあります。turtle
モジュールは標準ライブラリの一部なので、通常は別途インストールする必要はありません。
トラブルシューティング
- 環境変数の確認
(上級者向け) Pythonのパスが正しく設定されているか確認してください。 - Pythonの再インストール
Pythonのインストールが正しく行われているか確認し、必要であれば再インストールを検討してください。公式ウェブサイトから最新版をダウンロードすることをお勧めします。
描画が速すぎて何が起こっているか分からない
原因
タートルは非常に速く動くため、複雑な描画やアニメーションでは何が描かれているのか瞬時に終わってしまうことがあります。
- turtle.speed() の使用
タートルの描画速度を制御するためにspeed()
メソッドを使用します。0(最速、アニメーションなし)から10(最速、アニメーションあり)までの値、または文字列("fastest", "fast", "normal", "slow", "slowest")を指定できます。
import turtle
my_turtle = turtle.Turtle()
my_turtle.speed(1) # 速度を遅くする (1が最も遅く、10が最も速い)
for _ in range(4):
my_turtle.forward(100)
my_turtle.right(90)
turtle.done()
- screen.tracer() と screen.update() の使用
描画を完全に無効にし、すべての描画コマンドを実行した後に一度に画面を更新することで、非常に複雑な描画を高速化できます。アニメーションを停止したい場合に便利です。
import turtle
screen = turtle.Screen()
my_turtle = turtle.Turtle()
screen.tracer(0) # アニメーションをオフにする
for i in range(360):
my_turtle.forward(1)
my_turtle.right(1)
screen.update() # 画面を一度に更新
turtle.done()
- コメントアウトして試す
エラーが発生した行やブロックを一時的にコメントアウトして、問題の原因がそこにあるのかを特定します。 - インデントの確認
Pythonはインデントが重要です。特に繰り返し処理(for
ループやwhile
ループ)や条件分岐(if
文)の中でタートルコマンドを使用する場合、正しいインデントになっているか確認してください。 - コードをシンプルにする
複雑なコードでエラーが発生した場合、問題の箇所を特定するために、最小限のコードで同じエラーを再現できるか試してみてください。
turtle
モジュールは、簡単にグラフィックスを描画できるツールですが、その真価はオブジェクト指向的なアプローチ(公開クラスの利用)で発揮されます。
turtle.Turtle クラスの基本(単一のタートル)
最も基本的な例として、1つのタートルオブジェクトを作成し、それを使って図形を描画します。
import turtle
# 1. Screen オブジェクトを取得する(描画領域)
# 通常、Screenは一つだけ存在し、`turtle.Screen()`で取得します。
screen = turtle.Screen()
screen.bgcolor("lightgreen") # 背景色を設定
screen.title("My First Turtle Drawing") # ウィンドウのタイトルを設定
# 2. Turtle オブジェクトを作成する(描画する主体)
my_turtle = turtle.Turtle()
my_turtle.shape("turtle") # タートルの形を「カメ」にする
my_turtle.color("blue") # タートルの色を青にする
my_turtle.pensize(3) # ペンの太さを3にする
my_turtle.speed(5) # 描画速度を設定 (1-10, 0が最速)
# 3. タートルを使って図形を描画する
my_turtle.forward(100) # 100ピクセル前進
my_turtle.left(90) # 左に90度回転
my_turtle.forward(100)
my_turtle.left(90)
my_turtle.forward(100)
my_turtle.left(90)
my_turtle.forward(100) # これで正方形が描ける
# 4. 描画後にウィンドウが閉じないようにする
# ユーザーがクリックするまでウィンドウを表示し続ける
screen.exitonclick()
解説
screen.exitonclick()
: 描画が完了した後も、ユーザーがウィンドウをクリックするまでウィンドウが閉じないようにします。これは非常に重要です。my_turtle.forward()
,my_turtle.left()
:my_turtle
オブジェクトのメソッドを使って、タートルを動かし、線を描きます。my_turtle.shape()
,my_turtle.color()
,my_turtle.pensize()
,my_turtle.speed()
: 作成したmy_turtle
オブジェクトのメソッドを使って、タートルの見た目や振る舞いを設定します。my_turtle = turtle.Turtle()
: 実際に絵を描く「タートル」を表すTurtle
オブジェクトを作成します。これで、独自のタートルを持つことができます。screen.bgcolor()
やscreen.title()
:Screen
オブジェクトのメソッドを使って、画面の背景色やタイトルを設定します。screen = turtle.Screen()
: 描画が行われる「画面」全体を制御するScreen
オブジェクトを取得します。通常、このオブジェクトはプログラム中に一つだけ存在します。import turtle
:turtle
モジュールをインポートします。
複数のタートルを扱う例
オブジェクト指向プログラミングの大きな利点の一つは、同じクラスから複数のオブジェクトを作成し、それぞれを独立して制御できることです。ここでは、2つの異なるタートルを使って異なる図形を描画します。
import turtle
screen = turtle.Screen()
screen.bgcolor("lightgray")
screen.title("Multiple Turtles Demo")
screen.setup(width=600, height=400) # 画面サイズを設定
# 最初のタートルを作成(赤色、四角を描く)
red_turtle = turtle.Turtle()
red_turtle.shape("arrow")
red_turtle.color("red")
red_turtle.pensize(2)
red_turtle.penup() # ペンを上げて移動
red_turtle.goto(-100, 50) # 開始位置へ移動
red_turtle.pendown() # ペンを下ろして描画開始
red_turtle.speed(3)
for _ in range(4):
red_turtle.forward(80)
red_turtle.right(90)
# 2番目のタートルを作成(緑色、円を描く)
green_turtle = turtle.Turtle()
green_turtle.shape("circle")
green_turtle.color("green")
green_turtle.pensize(4)
green_turtle.penup() # ペンを上げて移動
green_turtle.goto(100, -50) # 開始位置へ移動
green_turtle.pendown() # ペンを下ろして描画開始
green_turtle.speed(2)
green_turtle.circle(60) # 半径60の円を描く
# タートルを非表示にする
red_turtle.hideturtle()
green_turtle.hideturtle()
screen.exitonclick()
解説
red_turtle.hideturtle()
: 描画後にタートル自体を非表示にしています。red_turtle.penup()
,red_turtle.goto()
,red_turtle.pendown()
: ペンを上げて移動することで、線を描かずにタートルを別の場所に移動させています。これにより、それぞれのタートルが独立した位置から描画を開始できます。- それぞれのオブジェクトに対して、独立して
shape()
,color()
,pensize()
,speed()
などのメソッドを呼び出し、異なる設定を与えています。 red_turtle = turtle.Turtle()
とgreen_turtle = turtle.Turtle()
: 異なる2つのTurtle
オブジェクトを作成しています。
turtle.Screen を使ったイベント処理の例
turtle.Screen
クラスは、ユーザーからの入力(キーボードやマウス)を処理するためのメソッドも提供します。これにより、インタラクティブなプログラムを作成できます。
import turtle
screen = turtle.Screen()
screen.bgcolor("lightyellow")
screen.title("Interactive Turtle")
player_turtle = turtle.Turtle()
player_turtle.shape("turtle")
player_turtle.color("purple")
player_turtle.pensize(2)
player_turtle.speed(0) # 最速でアニメーション
# キーボードイベントに対応する関数を定義
def move_forward():
player_turtle.forward(10)
def turn_left():
player_turtle.left(30) # 30度左に回転
def turn_right():
player_turtle.right(30) # 30度右に回転
# イベントリスナーを設定
screen.listen() # キーボード入力を受け付けるようにする
# 特定のキーが押されたときに、定義した関数を呼び出す
screen.onkey(move_forward, "Up") # 上矢印キーで前進
screen.onkey(turn_left, "Left") # 左矢印キーで左回転
screen.onkey(turn_right, "Right") # 右矢印キーで右回転
# クリックイベントに対応する関数を定義
def clear_drawing(x, y):
player_turtle.clear() # 描画を全て消去
player_turtle.penup()
player_turtle.home() # 初期位置に戻る
player_turtle.pendown()
screen.onclick(clear_drawing) # 画面をクリックしたら描画をクリア
screen.exitonclick()
player_turtle.home()
: タートルを初期位置(中心、向きは右)に戻します。player_turtle.clear()
: タートルの描画履歴を全て消去します。screen.onclick(関数名)
: 画面がクリックされたときに、対応する関数が呼び出されるように設定します。クリックイベントの関数は、クリックされたX座標とY座標を引数として受け取ります。screen.onkey(関数名, キー名)
: 指定されたキーが押されたときに、対応する関数が呼び出されるように設定します。ここでは、矢印キーを例にしています。screen.listen()
: キーボードからの入力を受け付ける準備をします。
turtle
モジュール内で、クラスを使わずにプログラミングする方法 これは、turtle
モジュールが提供する「手続き型(関数型)インターフェース」を指します。turtle
モジュール以外で、グラフィックプログラミングを行う方法 これは、他のグラフィックライブラリやフレームワークを指します。
ここでは、まず1番目の「turtle
モジュール内で、クラスを使わずにプログラミングする方法」について詳しく説明し、その後2番目の「turtle
モジュール以外の代替手段」について簡単に触れます。
Python turtle
モジュールの公開クラス以外のプログラミング方法(手続き型インターフェース)
turtle
モジュールは、オブジェクト指向プログラミング(公開クラス turtle.Turtle
と turtle.Screen
を使う方法)とは別に、よりシンプルで手続き的なインターフェースも提供しています。これは、特にプログラミング初心者がすぐにグラフィックスを描画し始めることを目的としています。
特徴
- 内部的には、これらの関数はデフォルトのタートルオブジェクトやスクリーンオブジェクトのメソッドを呼び出しています。
- モジュールレベルの関数を直接呼び出すだけで、デフォルトのタートルとスクリーンが自動的に作成され、操作されます。
turtle.Turtle()
やturtle.Screen()
のように明示的にオブジェクトを作成する必要がありません。
基本的な使い方(例:正方形を描く)
import turtle
# 明示的にTurtleオブジェクトを作成しない
# turtle.forward(), turtle.left() のように直接呼び出す
turtle.bgcolor("lightblue") # デフォルトのスクリーンに対して背景色を設定
turtle.pensize(3) # デフォルトのタートルに対してペンの太さを設定
turtle.color("red") # デフォルトのタートルに対して色を設定
turtle.speed(5) # デフォルトのタートルに対して速度を設定
for _ in range(4):
turtle.forward(100)
turtle.left(90)
# デフォルトのスクリーンに対して終了処理を行う
turtle.done() # または turtle.exitonclick()
解説
turtle.done()
やturtle.exitonclick()
も、デフォルトのScreen
オブジェクトに対して動作します。- 例えば、
turtle.forward(100)
は内部的にturtle.Turtle._getDefaultTurtle().forward(100)
のような処理を行っています(厳密な実装とは異なる場合がありますが、概念としてはこうです)。 - これにより、モジュールが自動的にシングルトン(単一のインスタンス)の
Turtle
オブジェクトとScreen
オブジェクトを作成し、これらの関数はそのシングルトンオブジェクトのメソッドを内部で呼び出しています。 import turtle
の後、turtle.bgcolor()
,turtle.pensize()
,turtle.forward()
などの関数を直接呼び出しています。
この方法の利点
- 少ない記述量
オブジェクトの作成や変数の割り当てを省略できます。 - シンプルさ
コードが短く、すぐに結果を見ることができるため、初心者がプログラミングの概念(ループなど)を学ぶのに非常に適しています。
この方法の欠点
- コードの可読性(大規模な場合)
プログラムが複雑になるにつれて、どの関数がどのタートルやスクリーンに作用しているのかが分かりにくくなる可能性があります。 - 制御の限界
画面全体のイベント処理(クリックやキー入力など)を詳細に制御する場合など、turtle.Screen()
オブジェクトを明示的に取得・操作する方が柔軟性が高まります。 - 複数のタートルを扱えない
この方法では、一度に1つのタートル(デフォルトのタートル)しか操作できません。複数の独立した描画エンティティが必要な場合は、オブジェクト指向のアプローチ(turtle.Turtle()
を使う方法)が必須です。
from turtle import *
の利用
さらに記述を簡略化するために、from turtle import *
という形式でインポートすることもあります。
from turtle import * # turtleモジュールから全ての名前(関数、クラスなど)をインポート
# turtle. をつけずに直接関数を呼び出せる
bgcolor("lightcoral")
pensize(5)
color("white")
speed(0) # 最速
for _ in range(3):
forward(120)
left(120)
done()
利点
- 最も簡潔な記述。
欠点
- どの関数がどのモジュールから来たものなのかが不明瞭になり、コードの可読性が低下する可能性があります。
- 名前空間の汚染
turtle
モジュール内のすべての名前(関数、クラス、定数など)がグローバル名前空間にインポートされるため、他のモジュールや自分で定義した変数名と衝突する可能性があります。これは大規模なプロジェクトでは特に問題になります。
- 複数のタートルを扱いたい、より複雑な描画やインタラクティブなプログラムを作成したい場合
turtle.Turtle()
とturtle.Screen()
を明示的に使うオブジェクト指向のアプローチが推奨されます。 - 初心者が簡単な実験をする場合や、単一のタートルでシンプルな図形を描く場合
手続き型インターフェース(import turtle
とturtle.forward()
など、またはfrom turtle import *
)は非常に便利です。
turtle
モジュールは学習用として優れていますが、より高度なグラフィック描画やGUIアプリケーション開発には、他のライブラリが使われます。
turtle
の機能だけでは不十分な場合は、目的(GUI、ゲーム、データ可視化、画像処理など)に応じた専門のライブラリを学ぶことになります。turtle
内でより高度な制御が必要な場合は、turtle.Turtle()
とturtle.Screen()
を使ったオブジェクト指向のアプローチに移行するのが良いでしょう。turtle
モジュールは、プログラミング学習の最初のステップ、特に描画の概念を視覚的に理解するのに最適です。