State Clearing in Python Turtle
I'm writing a program that asks a user for an integer > 0 which is used as the complexity factor for drawing a Koch curve. The program executes fine, once. When running a second time the Terminator
is invoked and the traceback points to what I think is the aTurtle
variable not clearing it's last state. If I restart the kernel, and clear all outputs, it works fine again once, then the issue repeats. What am I overlooking?
This was constructed and executed in Jupyter
and tested in qtconsole
as well. Code is listed below:
import turtle
aTurtle = turtle.Turtle()
#Functions
def drawLS(aTurtle, instructions):
for cmd in instructions:
if cmd == 'F':
aTurtle.forward(5)
elif cmd == '+':
aTurtle.right(70)
elif cmd == '-':
aTurtle.left(70)
else :
print('Error : %s is an unknown command '%cmd)
def applyProduction():
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for i in range(n):
newString = ""
for ch in axiom :
newString = newString + myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem():
win = turtle.Screen()
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction()
drawLS (aTurtle, newRules)
win.exitonclick()
#Main
while True:
try:
n = int(input("Enter an integer greater than 0: "))
break
except:
print ("Error, input was not an integer, please try again.")
if n < 1:
print ("Error, input was not an integer greater than 0.")
else:
lsystem()
python turtle-graphics
add a comment |
I'm writing a program that asks a user for an integer > 0 which is used as the complexity factor for drawing a Koch curve. The program executes fine, once. When running a second time the Terminator
is invoked and the traceback points to what I think is the aTurtle
variable not clearing it's last state. If I restart the kernel, and clear all outputs, it works fine again once, then the issue repeats. What am I overlooking?
This was constructed and executed in Jupyter
and tested in qtconsole
as well. Code is listed below:
import turtle
aTurtle = turtle.Turtle()
#Functions
def drawLS(aTurtle, instructions):
for cmd in instructions:
if cmd == 'F':
aTurtle.forward(5)
elif cmd == '+':
aTurtle.right(70)
elif cmd == '-':
aTurtle.left(70)
else :
print('Error : %s is an unknown command '%cmd)
def applyProduction():
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for i in range(n):
newString = ""
for ch in axiom :
newString = newString + myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem():
win = turtle.Screen()
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction()
drawLS (aTurtle, newRules)
win.exitonclick()
#Main
while True:
try:
n = int(input("Enter an integer greater than 0: "))
break
except:
print ("Error, input was not an integer, please try again.")
if n < 1:
print ("Error, input was not an integer greater than 0.")
else:
lsystem()
python turtle-graphics
add a comment |
I'm writing a program that asks a user for an integer > 0 which is used as the complexity factor for drawing a Koch curve. The program executes fine, once. When running a second time the Terminator
is invoked and the traceback points to what I think is the aTurtle
variable not clearing it's last state. If I restart the kernel, and clear all outputs, it works fine again once, then the issue repeats. What am I overlooking?
This was constructed and executed in Jupyter
and tested in qtconsole
as well. Code is listed below:
import turtle
aTurtle = turtle.Turtle()
#Functions
def drawLS(aTurtle, instructions):
for cmd in instructions:
if cmd == 'F':
aTurtle.forward(5)
elif cmd == '+':
aTurtle.right(70)
elif cmd == '-':
aTurtle.left(70)
else :
print('Error : %s is an unknown command '%cmd)
def applyProduction():
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for i in range(n):
newString = ""
for ch in axiom :
newString = newString + myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem():
win = turtle.Screen()
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction()
drawLS (aTurtle, newRules)
win.exitonclick()
#Main
while True:
try:
n = int(input("Enter an integer greater than 0: "))
break
except:
print ("Error, input was not an integer, please try again.")
if n < 1:
print ("Error, input was not an integer greater than 0.")
else:
lsystem()
python turtle-graphics
I'm writing a program that asks a user for an integer > 0 which is used as the complexity factor for drawing a Koch curve. The program executes fine, once. When running a second time the Terminator
is invoked and the traceback points to what I think is the aTurtle
variable not clearing it's last state. If I restart the kernel, and clear all outputs, it works fine again once, then the issue repeats. What am I overlooking?
This was constructed and executed in Jupyter
and tested in qtconsole
as well. Code is listed below:
import turtle
aTurtle = turtle.Turtle()
#Functions
def drawLS(aTurtle, instructions):
for cmd in instructions:
if cmd == 'F':
aTurtle.forward(5)
elif cmd == '+':
aTurtle.right(70)
elif cmd == '-':
aTurtle.left(70)
else :
print('Error : %s is an unknown command '%cmd)
def applyProduction():
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for i in range(n):
newString = ""
for ch in axiom :
newString = newString + myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem():
win = turtle.Screen()
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction()
drawLS (aTurtle, newRules)
win.exitonclick()
#Main
while True:
try:
n = int(input("Enter an integer greater than 0: "))
break
except:
print ("Error, input was not an integer, please try again.")
if n < 1:
print ("Error, input was not an integer greater than 0.")
else:
lsystem()
python turtle-graphics
python turtle-graphics
edited Nov 28 '18 at 21:49
cdlane
19.7k21245
19.7k21245
asked Nov 28 '18 at 19:58
P-SidesP-Sides
127
127
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Generally, you shouldn't plan to survive a win.exitonclick()
or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear()
or possibly win.reset()
. I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick()
, and to use the graphic numinput()
:
from turtle import Screen, Turtle
def drawLS(turtle, instructions):
for cmd in instructions:
if cmd == 'F':
turtle.forward(5)
elif cmd == '+':
turtle.right(70)
elif cmd == '-':
turtle.left(70)
else:
print('Error : %s is an unknown command '%cmd)
def applyProduction(n):
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for _ in range(n):
newString = ""
for ch in axiom:
newString += myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem(n):
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction(n)
drawLS(aTurtle, newRules)
def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
screen.onclick(None)
n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)
if n is not None:
screen.clear()
lsystem(int(n))
screen.onclick(prompt)
screen = Screen()
aTurtle = Turtle()
aTurtle.speed('fastest') # because I have no patience
prompt()
screen.mainloop()
When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.
Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?
– P-Sides
Nov 29 '18 at 22:25
@P-Sides, thenuminput()
method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number orNone
, never a negative. It does of course return afloat
so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)
– cdlane
Nov 29 '18 at 23:56
Ok thank you, this satisfies the original intent of the small program.
– P-Sides
Nov 30 '18 at 17:37
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53527194%2fstate-clearing-in-python-turtle%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Generally, you shouldn't plan to survive a win.exitonclick()
or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear()
or possibly win.reset()
. I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick()
, and to use the graphic numinput()
:
from turtle import Screen, Turtle
def drawLS(turtle, instructions):
for cmd in instructions:
if cmd == 'F':
turtle.forward(5)
elif cmd == '+':
turtle.right(70)
elif cmd == '-':
turtle.left(70)
else:
print('Error : %s is an unknown command '%cmd)
def applyProduction(n):
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for _ in range(n):
newString = ""
for ch in axiom:
newString += myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem(n):
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction(n)
drawLS(aTurtle, newRules)
def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
screen.onclick(None)
n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)
if n is not None:
screen.clear()
lsystem(int(n))
screen.onclick(prompt)
screen = Screen()
aTurtle = Turtle()
aTurtle.speed('fastest') # because I have no patience
prompt()
screen.mainloop()
When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.
Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?
– P-Sides
Nov 29 '18 at 22:25
@P-Sides, thenuminput()
method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number orNone
, never a negative. It does of course return afloat
so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)
– cdlane
Nov 29 '18 at 23:56
Ok thank you, this satisfies the original intent of the small program.
– P-Sides
Nov 30 '18 at 17:37
add a comment |
Generally, you shouldn't plan to survive a win.exitonclick()
or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear()
or possibly win.reset()
. I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick()
, and to use the graphic numinput()
:
from turtle import Screen, Turtle
def drawLS(turtle, instructions):
for cmd in instructions:
if cmd == 'F':
turtle.forward(5)
elif cmd == '+':
turtle.right(70)
elif cmd == '-':
turtle.left(70)
else:
print('Error : %s is an unknown command '%cmd)
def applyProduction(n):
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for _ in range(n):
newString = ""
for ch in axiom:
newString += myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem(n):
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction(n)
drawLS(aTurtle, newRules)
def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
screen.onclick(None)
n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)
if n is not None:
screen.clear()
lsystem(int(n))
screen.onclick(prompt)
screen = Screen()
aTurtle = Turtle()
aTurtle.speed('fastest') # because I have no patience
prompt()
screen.mainloop()
When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.
Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?
– P-Sides
Nov 29 '18 at 22:25
@P-Sides, thenuminput()
method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number orNone
, never a negative. It does of course return afloat
so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)
– cdlane
Nov 29 '18 at 23:56
Ok thank you, this satisfies the original intent of the small program.
– P-Sides
Nov 30 '18 at 17:37
add a comment |
Generally, you shouldn't plan to survive a win.exitonclick()
or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear()
or possibly win.reset()
. I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick()
, and to use the graphic numinput()
:
from turtle import Screen, Turtle
def drawLS(turtle, instructions):
for cmd in instructions:
if cmd == 'F':
turtle.forward(5)
elif cmd == '+':
turtle.right(70)
elif cmd == '-':
turtle.left(70)
else:
print('Error : %s is an unknown command '%cmd)
def applyProduction(n):
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for _ in range(n):
newString = ""
for ch in axiom:
newString += myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem(n):
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction(n)
drawLS(aTurtle, newRules)
def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
screen.onclick(None)
n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)
if n is not None:
screen.clear()
lsystem(int(n))
screen.onclick(prompt)
screen = Screen()
aTurtle = Turtle()
aTurtle.speed('fastest') # because I have no patience
prompt()
screen.mainloop()
When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.
Generally, you shouldn't plan to survive a win.exitonclick()
or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear()
or possibly win.reset()
. I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick()
, and to use the graphic numinput()
:
from turtle import Screen, Turtle
def drawLS(turtle, instructions):
for cmd in instructions:
if cmd == 'F':
turtle.forward(5)
elif cmd == '+':
turtle.right(70)
elif cmd == '-':
turtle.left(70)
else:
print('Error : %s is an unknown command '%cmd)
def applyProduction(n):
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for _ in range(n):
newString = ""
for ch in axiom:
newString += myRules.get(ch, ch)
axiom = newString
return axiom
def lsystem(n):
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction(n)
drawLS(aTurtle, newRules)
def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
screen.onclick(None)
n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)
if n is not None:
screen.clear()
lsystem(int(n))
screen.onclick(prompt)
screen = Screen()
aTurtle = Turtle()
aTurtle.speed('fastest') # because I have no patience
prompt()
screen.mainloop()
When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.
answered Nov 28 '18 at 21:40
cdlanecdlane
19.7k21245
19.7k21245
Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?
– P-Sides
Nov 29 '18 at 22:25
@P-Sides, thenuminput()
method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number orNone
, never a negative. It does of course return afloat
so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)
– cdlane
Nov 29 '18 at 23:56
Ok thank you, this satisfies the original intent of the small program.
– P-Sides
Nov 30 '18 at 17:37
add a comment |
Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?
– P-Sides
Nov 29 '18 at 22:25
@P-Sides, thenuminput()
method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number orNone
, never a negative. It does of course return afloat
so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)
– cdlane
Nov 29 '18 at 23:56
Ok thank you, this satisfies the original intent of the small program.
– P-Sides
Nov 30 '18 at 17:37
Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?
– P-Sides
Nov 29 '18 at 22:25
Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?
– P-Sides
Nov 29 '18 at 22:25
@P-Sides, the
numinput()
method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None
, never a negative. It does of course return a float
so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)– cdlane
Nov 29 '18 at 23:56
@P-Sides, the
numinput()
method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None
, never a negative. It does of course return a float
so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)– cdlane
Nov 29 '18 at 23:56
Ok thank you, this satisfies the original intent of the small program.
– P-Sides
Nov 30 '18 at 17:37
Ok thank you, this satisfies the original intent of the small program.
– P-Sides
Nov 30 '18 at 17:37
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53527194%2fstate-clearing-in-python-turtle%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown