class Celsius(object):
def __init__(self, value=0.0):
self.value = float(value)
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = float(value)
class Temperature(object):
celsius = Celsius()
Why do I need the descriptor class? Please explain using this example or the one you think is better.
What is instance and owner here? (in __get__). So my question is, what is the purpose of the third parameter here?
How would I call/ use this example?
Answer:
The descriptor is how Python's property type is implemented. A descriptor simply implements __get__, __set__, etc. and is then added to another class in its definition (as you did above with the Temperature class). For example:
temp=Temperature()
temp.celsius #calls celsius.__get__
Accessing the property you assigned the descriptor to (celsius in the above example) calls the appropriate descriptor method.
instance in __get__ is the instance of the class (so above, __get__ would receive temp, while owner is the class with the descriptor (so it would be Temperature).
You need to use a descriptor class to encapsulate the logic that powers it. That way, if the descriptor is used to cache some expensive operation (for example), it could store the value on itself and not its class.
An article about descriptors can be found here.
EDIT: As jchl pointed out in the comments, if you simply try Temperature.celsius, instance will be None.
descriptor: TurtleMethodCommand
pensize: accessing the property
class: TurtleCommander
instance: t
owner: TurtleCommander
目录threaded_turtle下的库文件:
cat __init__.py
"""
This package brings the functionality of Python's "turtle" package
with threading.
Turtle does not support threading, so this implements a queue which
serializes the access to turtle API from the main thread, which is
easily accessible from the turtle threads.
Usage:
# Initialize one TurtleThreadSerializer
ctrl = ThreadSerializer()
# Initialize TurtleThread instances as you want
# each represents a separate turtle, running in a separate thread
def run(my_turtle, angle):
my_turtle.left(angle)
for i in range(10, 0, -1):
my_turtle.left(5)
my_turtle.forward(i)
turtle1 = TurtleThread(ctrl, target=run, args=(0,))
turtle2 = TurtleThread(ctrl, target=run, args=(90,))
turtle3 = TurtleThread(ctrl, target=run, args=(180,))
turtle4 = TurtleThread(ctrl, target=run, args=(270,))
# Start all turtles:
turtle1.start()
turtle2.start()
turtle3.start()
turtle4.start()
# Start the main controller:
ctrl.run_forever()
"""
from threaded_turtle.thread_serializer import ThreadSerializer
from threaded_turtle.turtle_thread import TurtleThread
cat turtle_serializer.py
from turtle import Turtle
from threaded_turtle.thread_serializer import MethodCommand
class TurtleMethodCommand(MethodCommand):
"""The MethodCommand for Turtle commands
Represents a method of turtle.Turtle.
The class on which this is defined must have these two attributes:
- turtle - instnce of Python built-in turtle.Turtle
- thread_serializer - instance of ThreadSerializer
"""
def _execute(self, threaded_turtle_instance, command_name, args, kwargs):
threadless_turtle = threaded_turtle_instance.turtle
method = getattr(threadless_turtle, command_name)
return method(*args, **kwargs)
def _get_thread_serializer(self, instance):
return instance.thread_serializer
class TurtleCommander:
def __init__(self, thread_serializer, turtle=None):
self.thread_serializer = thread_serializer
if turtle is None:
self.turtle = Turtle()
elif isinstance(turtle, TurtleCommander):
self.turtle = turtle.turtle
else:
assert isinstance(turtle, Turtle)
self.turtle = turtle
forward = TurtleMethodCommand()
fd = TurtleMethodCommand()
backward = TurtleMethodCommand()
bk = TurtleMethodCommand()
back = TurtleMethodCommand()
right = TurtleMethodCommand()
rt = TurtleMethodCommand()
left = TurtleMethodCommand()
lt = TurtleMethodCommand()
goto = TurtleMethodCommand()
setpos = TurtleMethodCommand()
setposition = TurtleMethodCommand()
setx = TurtleMethodCommand()
sety = TurtleMethodCommand()
setheading = TurtleMethodCommand()
seth = TurtleMethodCommand()
home = TurtleMethodCommand()
circle = TurtleMethodCommand()
dot = TurtleMethodCommand()
stamp = TurtleMethodCommand()
clearstamp = TurtleMethodCommand()
clearstamps = TurtleMethodCommand()
undo = TurtleMethodCommand()
speed = TurtleMethodCommand()
position = TurtleMethodCommand()
pos = TurtleMethodCommand()
towards = TurtleMethodCommand()
xcor = TurtleMethodCommand()
ycor = TurtleMethodCommand()
heading = TurtleMethodCommand()
distance = TurtleMethodCommand()
degrees = TurtleMethodCommand()
radians = TurtleMethodCommand()
pendown = TurtleMethodCommand()
pd = TurtleMethodCommand()
down = TurtleMethodCommand()
penup = TurtleMethodCommand()
pu = TurtleMethodCommand()
up = TurtleMethodCommand()
pensize = TurtleMethodCommand()
width = TurtleMethodCommand()
pen = TurtleMethodCommand()
isdown = TurtleMethodCommand()
color = TurtleMethodCommand()
pencolor = TurtleMethodCommand()
fillcolor = TurtleMethodCommand()
filling = TurtleMethodCommand()
begin_fill = TurtleMethodCommand()
end_fill = TurtleMethodCommand()
reset = TurtleMethodCommand()
clear = TurtleMethodCommand()
write = TurtleMethodCommand()
showturtle = TurtleMethodCommand()
st = TurtleMethodCommand()
hideturtle = TurtleMethodCommand()
ht = TurtleMethodCommand()
isvisible = TurtleMethodCommand()
shape = TurtleMethodCommand()
resizemode = TurtleMethodCommand()
shapesize = TurtleMethodCommand()
turtlesize = TurtleMethodCommand()
shearfactor = TurtleMethodCommand()
settiltangle = TurtleMethodCommand()
tiltangle = TurtleMethodCommand()
tilt = TurtleMethodCommand()
shapetransform = TurtleMethodCommand()
get_shapepoly = TurtleMethodCommand()
begin_poly = TurtleMethodCommand()
end_poly = TurtleMethodCommand()
get_poly = TurtleMethodCommand()
clone = TurtleMethodCommand()
getturtle = TurtleMethodCommand()
getpen = TurtleMethodCommand()
getscreen = TurtleMethodCommand()
setundobuffer = TurtleMethodCommand()
undobufferentries = TurtleMethodCommand()
cat thread_serializer.py
"""
Serialize thread execution using a queue.
When multiple thread are needed to be used in an environment where
multithreading is not supported, this module provides the functionality
for executing threads which send their commands to a queue which is then
executed sequentially in the main thread.
The functionality consists of:
- thread serializer - which puts commands in a queue when execute_command
is called from different threads, and then executes
the commands after reading them from the queue in the
main thread
- method command - descriptor which creates a method to be called from a
thread; when called, the method creates a command in
thread serializer and waits for it to be executed, so
it seems as if it was executed within the thread
"""
import queue
import threading
class ThreadSerializer:
"""Sequentially executes commands it finds in its queue"""
def __init__(self):
self._queue = queue.Queue()
def run_forever(self, queue_timeout=None):
"""Read commands from the queue and execute them forever
If queue_timeout is given, this method will raise
queue.Empty if there is noting in the queue for that number
if seconds.
"""
while True:
command = self._queue.get(timeout=queue_timeout)
command.execute()
def execute_command(self, command):
"""Put command in the queue, wait for the result and return it"""
self._queue.put(command)
return command.wait_for_result()
class MethodCommand:
"""A descriptor which turns methods into commands
Abstract class. Implement methods _execute and _get_thread_serializer:
* _execute executes a command. It will always be executed from the main thread.
* _get_thread_serializer return the thread serialized which executes commands
Usage example:
If a class defines a MethodCommand named foo, like this:
class ClassTwo:
foo = ImplementationOfMethodCommand()
then foo can be called as a method and it will execute
a command named "foo" with arguments passed to the method
"""
def __init__(self, command_name=None):
"""
Arguments:
command_name: name of the command, defaults to the descriptor name
"""
self._command_name = command_name
def _execute(self, instance, command_name, args, kwargs):
"""Override this method. It should return a Command instance."""
raise NotImplementedError()
def _get_thread_serializer(self, instance):
"""Override this method. It should return a ThreadSerializer instance."""
raise NotImplementedError()
def _get_redirected_func(self, instance):
serializer = self._get_thread_serializer(instance)
def func(*a, **kw):
execute = lambda: self._execute(instance, self._command_name, a, kw)
return serializer.execute_command(_Command(execute))
func.__qualname__ = "command<{}>".format(self._command_name)
return func
def __get__(self, instance, owner):
if instance is not None:
return self._get_redirected_func(instance)
else:
def unbound_f(inst, *a, **kw):
bound_f = self._get_redirected_func(inst)
return bound_f(*a, **kw)
unbound_f.__qualname__ = "unbound command<{}>".format(self._command_name)
return unbound_f
def __set_name__(self, owner, name):
if self._command_name is None:
self._command_name = name
class _Command:
"""A command to be executed in another thread"""
def __init__(self, execute_callback):
self._result_ready_event = threading.Event()
self._result = None
self._execute_callback = execute_callback
def execute(self):
self._result = self._execute_callback()
self._result_ready_event.set()
def wait_for_result(self):
self._result_ready_event.wait()
return self._result
cat turtle_thread.py
import threading
from threaded_turtle.turtle_serializer import TurtleCommander
class TurtleThread(threading.Thread):
"""A thread which knows how to handle a turtle ;)
The constructor takes two additional arguments compared to vanilla Thread:
- thread_serializer - the object which makes it possible to
run turtles in threads
- turtle - the optional turtle.TurtleCommander, if omitted,
a new one will be created
There are two main ways to use it:
- if the thread is implemented by overriding the run method, use self.turtle
as if it was a normal turtle.Turtle which can run in a thread
- if the thread is initialized with a "target" argument, the target will
receive the turtle as the first argument, plus all args and kwargs
"""
def __init__(self, thread_serializer, turtle=None, target=None, name=None,
args=(), kwargs={}, daemon=None):
self.turtle = TurtleCommander(thread_serializer, turtle)
if target is not None:
args = (self.turtle,) + tuple(args)
super().__init__(target=target, name=name, args=args, kwargs=kwargs, daemon=daemon)
主程序:
# coding=utf-8
import turtle
from threaded_turtle import ThreadSerializer, TurtleThread
from datetime import *
import math as m
turtle.colormode(255)
turtle.delay(0)
def Skip(step):
turtle.penup()
turtle.forward(step)
turtle.pendown()
def mkHand(name, length):
# 注册Turtle形状,建立表针Turtle
turtle.reset()
Skip(-length * 0.1)
# 开始记录多边形的顶点。当前的乌龟位置是多边形的第一个顶点。
turtle.begin_poly()
turtle.forward(length * 1.1)
# 停止记录多边形的顶点。当前的乌龟位置是多边形的最后一个顶点。将与第一个顶点相连。
turtle.end_poly()
# 返回最后记录的多边形。
handForm = turtle.get_poly()
turtle.register_shape(name, handForm)
def Init():
global secHand, minHand, hurHand, printer
# 重置Turtle指向北
turtle.mode("logo")
# 建立三个表针Turtle并初始化
mkHand("secHand", 135)
mkHand("minHand", 125)
mkHand("hurHand", 90)
secHand = turtle.Turtle()
secHand.shape("secHand")
minHand = turtle.Turtle()
minHand.shape("minHand")
hurHand = turtle.Turtle()
hurHand.shape("hurHand")
for hand in secHand, minHand, hurHand:
hand.shapesize(1, 1, 3)
hand.speed(0)
# 建立输出文字Turtle
printer = turtle.Turtle()
# 隐藏画笔的turtle形状
printer.hideturtle()
printer.penup()
def SetupClock(radius):
# 建立表的外框
turtle.reset()
turtle.pensize(7)
turtle.pencolor("#ff5500")
turtle.fillcolor("green")
for i in range(60):
Skip(radius)
if i % 5 == 0:
turtle.forward(20)
Skip(-radius - 20)
Skip(radius + 20)
if i == 0:
turtle.write(int(12), align="center", font=("Courier", 14, "bold"))
elif i == 30:
Skip(25)
turtle.write(int(i / 5), align="center", font=("Courier", 14, "bold"))
Skip(-25)
elif (i == 25 or i == 35):
Skip(20)
turtle.write(int(i / 5), align="center", font=("Courier", 14, "bold"))
Skip(-20)
else:
turtle.write(int(i / 5), align="center", font=("Courier", 14, "bold"))
Skip(-radius - 20)
else:
turtle.dot(5)
Skip(-radius)
turtle.right(6)
def Week(t):
week = ["星期一", "星期二", "星期三",
"星期四", "星期五", "星期六", "星期日"]
return week[t.weekday()]
def Date(t):
y = t.year
m = t.month
d = t.day
return "%s-%d-%d" % (y, m, d)
def Tick():
# 绘制表针的动态显示
t = datetime.today()
second = t.second + t.microsecond * 0.000001
minute = t.minute + second / 60.0
hour = t.hour + minute / 60.0
secHand.setheading(6 * second)
minHand.setheading(6 * minute)
hurHand.setheading(30 * hour)
turtle.tracer(False)
printer.forward(65)
printer.write(Week(t), align="center",
font=("Courier", 14, "bold"))
printer.back(130)
printer.write(Date(t), align="center",
font=("Courier", 14, "bold"))
printer.home()
turtle.tracer(True)
# 100ms后继续调用tick
turtle.ontimer(Tick, 100)
def main():
# 打开/关闭龟动画,并为更新图纸设置延迟。
# turtle.tracer(False)
turtle.speed(0)
Init()
SetupClock(160)
turtle.tracer(True)
Tick()
turtle.mainloop()
turtle.mode("standard")
ctrl = ThreadSerializer() ## <-- create a serializer
t1=turtle.Turtle()
t2=turtle.Turtle()
t2.right(0)
t2.pu()
t6=turtle.Turtle()
t6.right(45)
t6.pu()
t7=turtle.Turtle()
t7.right(90)
t7.pu()
t8=turtle.Turtle()
t8.right(135)
t8.pu()
t9=turtle.Turtle()
t9.right(180)
t9.pu()
t10=turtle.Turtle()
t10.right(225)
t10.pu()
t11=turtle.Turtle()
t11.right(270)
t11.pu()
t12=turtle.Turtle()
t12.right(315)
t12.pu()
t4=turtle.Turtle()
t1.screen.setup(width=1500, height=900)
t1.pu()
t4.pu()
t1.speed(0)
#t2.speed(6)
t4.speed(0)
t4.goto(-100, -100)
t1.goto(-400, 200)
t2.goto(200, 100)
t6.goto(200, 100)
t7.goto(200, 100)
t8.goto(200, 100)
t9.goto(200, 100)
t10.goto(200, 100)
t11.goto(200, 100)
t12.goto(200, 100)
def tes1(t1):
t1.pensize(4) # 设置画笔的大小
t1.color("Hotpink", "pink") # 设置画笔颜色和填充颜色(pink)
# t1.speed(0) # 设置画笔速度为10
#鼻子
t1.pu() # 提笔
# t1.goto(-100,100) # 画笔前往坐标(-100,100)
t1.pd() # 下笔
t1.seth(-30) # 笔的角度为-30°
t1.begin_fill() # 外形填充的开始标志
a=0.4
for i in range(120):
if 0<=i<30 or 60<=i<90:
a=a+0.08
t1.lt(3) #向左转3度
t1.fd(a) #向前走a的步长
else:
a=a-0.08
t1.lt(3)
t1.fd(a)
t1.end_fill() # 依据轮廓填充
t1.pu() # 提笔
t1.seth(90) # 笔的角度为90度
t1.fd(25) # 向前移动25
t1.seth(0) # 转换画笔的角度为0
t1.fd(10)
t1.pd()
t1.pencolor("HotPink") # 设置画笔颜色
t1.seth(10)
t1.begin_fill()
t1.circle(5) # 画一个半径为5的圆
t1.color("Brown") # 设置画笔和填充颜色
t1.end_fill()
t1.pu()
t1.seth(0)
t1.fd(20)
t1.pd()
t1.pencolor("HotPink")
t1.seth(10)
t1.begin_fill()
t1.circle(5)
t1.color("Brown")
t1.end_fill()
#头
t1.color("HotPink","pink")
t1.pu()
t1.seth(90)
t1.fd(41)
t1.seth(0)
t1.fd(0)
t1.pd()
t1.begin_fill()
t1.seth(180)
t1.circle(300,-30) # 顺时针画一个半径为300,圆心角为30°的园
t1.circle(100,-60)
t1.circle(80,-100)
t1.circle(150,-20)
t1.circle(60,-95)
t1.seth(161)
t1.circle(-300,15)
t1.pu()
t1.goto(-400,200)
t1.pd()
t1.seth(-30)
a=0.4
for i in range(60):
if 0<=i<30 or 60<=i<90:
a=a+0.08
t1.lt(3) #向左转3度
t1.fd(a) #向前走a的步长
else:
a=a-0.08
t1.lt(3)
t1.fd(a)
t1.end_fill()
#耳朵
t1.color("HotPink","pink")
t1.pu()
t1.seth(90)
t1.fd(-7)
t1.seth(0)
t1.fd(70)
t1.pd()
t1.begin_fill()
t1.seth(100)
t1.circle(-50,50)
t1.circle(-10,120)
t1.circle(-50,54)
t1.end_fill()
t1.pu()
t1.seth(90)
t1.fd(-12)
t1.seth(0)
t1.fd(30)
t1.pd()
t1.begin_fill()
t1.seth(100)
t1.circle(-50,50)
t1.circle(-10,120)
t1.circle(-50,56)
t1.end_fill()
#眼睛
t1.color("HotPink", "white")
t1.pu()
t1.seth(90)
t1.fd(-20)
t1.seth(0)
t1.fd(-95)
t1.pd()
t1.begin_fill()
t1.circle(15)
t1.end_fill()
t1.color("black")
t1.pu()
t1.seth(90)
t1.fd(12)
t1.seth(0)
t1.fd(-3)
t1.pd()
t1.begin_fill()
t1.circle(3)
t1.end_fill()
t1.color("HotPink", "white")
t1.pu()
t1.seth(90)
t1.fd(-25)
t1.seth(0)
t1.fd(40)
t1.pd()
t1.begin_fill()
t1.circle(15)
t1.end_fill()
t1.color("black")
t1.pu()
t1.seth(90)
t1.fd(12)
t1.seth(0)
t1.fd(-3)
t1.pd()
t1.begin_fill()
t1.circle(3)
t1.end_fill()
#腮
t1.color("HotPink")
t1.pu()
t1.seth(90)
t1.fd(-95)
t1.seth(0)
t1.fd(65)
t1.pd()
t1.begin_fill()
t1.circle(30)
t1.end_fill()
#嘴
t1.color("red")
t1.pu()
t1.seth(90)
t1.fd(15)
t1.seth(0)
t1.fd(-100)
t1.pd()
t1.seth(-80)
t1.circle(30,40)
t1.circle(40,80)
#身体
t1.color("red")
t1.pu()
t1.seth(90)
t1.fd(-20)
t1.seth(0)
t1.fd(-78)
t1.pd()
t1.begin_fill()
t1.seth(-130)
t1.circle(100,10)
t1.circle(300,30)
t1.seth(0)
t1.fd(230)
t1.seth(90)
t1.circle(300,30)
t1.circle(100,3)
t1.color("Red")
t1.seth(-135)
t1.circle(-80,63)
t1.circle(-150,24)
t1.end_fill()
#手
t1.color("HotPink")
t1.pu()
t1.seth(90)
t1.fd(-40)
t1.seth(0)
t1.fd(-27)
t1.pd()
t1.seth(-160)
t1.circle(300,15)
t1.pu()
t1.seth(90)
t1.fd(15)
t1.seth(0)
t1.fd(0)
t1.pd()
t1.seth(-10)
t1.circle(-20,90)
t1.pu()
t1.seth(90)
t1.fd(30)
t1.seth(0)
t1.fd(237)
t1.pd()
t1.seth(-20)
t1.circle(-300,15)
t1.pu()
t1.seth(90)
t1.fd(20)
t1.seth(0)
t1.fd(0)
t1.pd()
t1.seth(-170)
t1.circle(20,90)
#脚
t1.pensize(10)
t1.color("Tomato")
t1.pu()
t1.seth(90)
t1.fd(-75)
t1.seth(0)
t1.fd(-180)
t1.pd()
t1.seth(-90)
t1.fd(40)
t1.seth(-180)
t1.color("black")
t1.pensize(15)
t1.fd(20)
t1.pensize(10)
t1.color("Tomato")
t1.pu()
t1.seth(90)
t1.fd(40)
t1.seth(0)
t1.fd(90)
t1.pd()
t1.seth(-90)
t1.fd(40)
t1.seth(-180)
t1.color("black")
t1.pensize(15)
t1.fd(20)
#尾巴
t1.pensize(4)
t1.color("Pink")
t1.pu()
t1.seth(90)
t1.fd(70)
t1.seth(0)
t1.fd(95)
t1.pd()
t1.seth(0)
t1.circle(70,20)
t1.circle(10,330)
t1.circle(70,30)
"""
def test2(t2):
t2.speed(1)
t2.pd()
t2.pensize(30)
t2.pencolor("green")
t2.seth(-40) # 前进的方向
for _ in range(2):
t2.circle(70, 80)
t2.circle(-70, 80)
t2.circle(70, 40)
t2.forward(35) # 直线前进
t2.circle(15, 180)
t2.forward(70/4)
def tes2(t2): ## <-- additional argument
t2.pensize(4) # 设置画笔的大小
t2.color("black") # 设置画笔颜色和填充颜色(pink)
# t2.speed(0) # 设置画笔速度为10
t2.pu() # 提笔
t2.pd() # 下笔
t2.seth(-90)
a=10
for i in range(72):
if 0<=i<18 or 36<=i<54:
a=a+0.5
t2.lt(5) #向左转3度
t2.fd(a) #向前走a的步长
else:
a=a-0.5
t2.lt(5)
t2.fd(a)
t2.pu()
t2.seth(0)
t2.fd(40)
t2.seth(90)
t2.fd(100)
t2.seth(120)
t2.color('black')
t2.begin_fill()
t2.pd()
t2.circle(-50,180)
t2.end_fill()
t2.heading()
t2.pu()
t2.seth(0)
t2.fd(100)
t2.seth(60)
t2.color('black')
t2.begin_fill()
t2.pd()
t2.circle(-50,180)
t2.end_fill()
t2.pos()
t2.pu()
t2.goto(200,215)
t2.seth(-30)
t2.pd()
t2.begin_fill()
a=1
for i in range(72):
if 0<=i<18 or 36<=i<54:
a=a+0.2
t2.lt(5) #向左转3度
t2.fd(a) #向前走a的步长
else:
a=a-0.2
t2.lt(5)
t2.fd(a)
t2.end_fill()
t2.goto(220, 255)
t2.dot(15, "white")
t2.pu()
t2.goto(350,215)
t2.seth(30)
t2.pd()
t2.begin_fill()
a=1
for i in range(72):
if 0<=i<18 or 36<=i<54:
a=a+0.2
t2.lt(5) #向左转3度
t2.fd(a) #向前走a的步长
else:
a=a-0.2
t2.lt(5)
t2.fd(a)
t2.end_fill()
t2.pu()
t2.goto(325, 255)
t2.dot(15, "white")
t2.goto(280,170)
t2.dot(40, "black")
t2.goto(220, 130)
t2.seth(-40)
t2.pd()
t2.circle(100,80)
t2.pu()
t2.goto(210, 80)
t2.seth(-30)
t2.begin_fill()
t2.pd()
a=6
for i in range(72):
if 0<=i<18 or 36<=i<54:
a=a+0.1
t2.rt(5) #向左转3度
t2.fd(a) #向前走a的步长
else:
a=a-0.1
t2.rt(5)
t2.fd(a)
t2.end_fill()
t2.pu()
t2.goto(350,100)
t2.seth(30)
t2.begin_fill()
t2.pd()
a=3
for i in range(72):
if 0<=i<18 or 36<=i<54:
a=a+0.5
t2.rt(5) #向左转3度
t2.fd(a) #向前走a的步长
else:
a=a-0.5
t2.rt(5)
t2.fd(a)
t2.end_fill()
t2.pu()
t2.goto(80,-80)
t2.seth(-180)
t2.begin_fill()
t2.pd()
t2.circle(80,180)
t2.circle(1380,7)
t2.circle(50,80)
t2.seth(90)
t2.fd(70)
t2.seth(170)
t2.circle(1400,9)
t2.end_fill()
t2.pu()
t2.goto(520, -90)
t2.seth(0)
t2.begin_fill()
t2.pd()
t2.circle(-70,180)
t2.circle(-1380,7)
t2.circle(-50,60)
t2.seth(90)
t2.fd(70)
t2.seth(10)
t2.circle(-1400,9)
t2.end_fill()
a=2
for i in range(72):
if 0<=i<18 or 36<=i<54:
a=a+1
t2.lt(5) #向左转3度
t2.fd(a) #向前走a的步长
else:
a=a-1
t2.lt(5)
t2.fd(a)
t2.end_fill()
"""
def test3(t4):
t4.pensize(4) # 设置画笔的大小
# t4.colormode(255) # 设置GBK颜色范围为0-255
t4.color((0,0,255),"blue") # 设置画笔颜色和填充颜色(pink)
# t4.setup(800,600) # 设置主窗口的大小为840*500
t4.speed(0) # 设置画笔速度为10
#头部
t4.hideturtle()
t4.pu() # 提笔
t4.goto(-50,-400) # 画笔前往坐标(0,0)
t4.seth(150)
t4.pd() # 下笔
t4.begin_fill()
t4.color(0,0,255)
for i in range(75):
t4.rt(4)
t4.forward(2*m.pi*100/90)
t4.seth(0)
t4.backward(10)
t4.seth(30)
for i in range(75):
t4.lt(4)
t4.forward(2*m.pi*80/90)
t4.seth(0)
t4.backward(10)
t4.end_fill()
#眼睛
t4.pu()
t4.begin_fill()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(-15,40*m.sqrt(3)+60-400)
t4.pd()
t4.circle(15)
t4.color(255,255,255)
t4.end_fill()
t4.pu()
t4.begin_fill()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(-15,40*m.sqrt(3)+60-400)
t4.pd()
t4.circle(5)
t4.color(0,0,0)
t4.end_fill()
t4.pu()
t4.begin_fill()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(15,40*m.sqrt(3)+60-400)
t4.pd()
t4.circle(15)
t4.color(255,255,255)
t4.end_fill()
t4.pu()
t4.begin_fill()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(15,40*m.sqrt(3)+60-400)
t4.pd()
t4.circle(5)
t4.color(0,0,0)
t4.end_fill()
#鼻子
t4.pu()
t4.pensize(3)
t4.pencolor(255,0,0)
t4.goto(0,40*m.sqrt(3)+40-400)
t4.pd()
t4.begin_fill()
t4.color(255,0,0)
t4.circle(10)
t4.end_fill()
#嘴巴
t4.pu()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(0,40*m.sqrt(3)+40-400)
t4.pd()
t4.seth(-90)
t4.forward(50)
t4.pu()
t4.goto(-50,90-10*m.sqrt(3)-400)
t4.seth(-30)
t4.pd()
for i in range(30):
t4.lt(2)
t4.forward(2*m.pi*100/180)
#胡须
t4.pu()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(-30,40*m.sqrt(3)+25-400)
t4.seth(0)
t4.pd()
t4.backward(40)
t4.pu()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(-30,40*m.sqrt(3)+15-400)
t4.pd()
t4.seth(30)
t4.backward(40)
t4.pu()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(-30,40*m.sqrt(3)+35-400)
t4.pd()
t4.seth(-30)
t4.backward(40)
t4.pu()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(30, 40*m.sqrt(3)+25-400)
t4.seth(0)
t4.pd()
t4.forward(40)
t4.pu()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(30,40*m.sqrt(3)+35-400)
t4.pd()
t4.seth(30)
t4.forward(40)
t4.pu()
t4.pensize(3)
t4.pencolor(0,0,0)
t4.goto(30,40*m.sqrt(3)+15-400)
t4.pd()
t4.seth(-30)
t4.forward(40)
# a=0.4
# for i in range(360):
# if 0<=i<90 or 180<=i<270:
# a=a+0.008
# t4.lt(1) #向左转3度
# t4.fd(a) #向前走a的步长
# else:
# a=a-0.008
# t4.lt(1)
# t4.fd(a)
# t4.done()
def test2(t2):
#
# t2.pd()
# t = [t2 for i in range(8)]
# print("t is:", t)
# for i, j in enumerate(t2):
# j.right(i*45)
t2.pd()
t2.speed(0)
for i in range(360):
t2.forward(1)
t2.right(1)
t = TurtleThread(ctrl, t1, target=tes1) ## <-- additional arguments
t.daemon = True
t.start()
t3 = TurtleThread(ctrl, t2, target=test2) ## <-- additional arguments
t3.daemon = True
t3.start()
t13 = TurtleThread(ctrl, t6, target=test2) ## <-- additional arguments
t13.daemon = True
t13.start()
t14 = TurtleThread(ctrl, t7, target=test2) ## <-- additional arguments
t14.daemon = True
t14.start()
t15 = TurtleThread(ctrl, t8, target=test2) ## <-- additional arguments
t15.daemon = True
t15.start()
t16 = TurtleThread(ctrl, t9, target=test2) ## <-- additional arguments
t16.daemon = True
t16.start()
t17 = TurtleThread(ctrl, t10, target=test2) ## <-- additional arguments
t17.daemon = True
t17.start()
t18 = TurtleThread(ctrl, t11, target=test2) ## <-- additional arguments
t18.daemon = True
t18.start()
t19 = TurtleThread(ctrl, t12, target=test2) ## <-- additional arguments
t19.daemon = True
t19.start()
t5 = TurtleThread(ctrl, t4, target=test3)
t5.daemon = True
t5.start()
#
try:
ctrl.run_forever(0)
except:
main()
t1.screen.exitonclick()