类型错误与执行()
我想制作一个程序,根据用户输入绘制某些行。类型错误与执行()
#import turtle program
#called it cassy cause I was trying to come up with a fun name for an arrow
that they call 'classic'. I tried ok.
import turtle
cassy = turtle.Turtle()
cassy.shape('classic')
#set's the window shape, so I can give myself more room
#for reference, putting startx and y as none centers it
turtle.setup(width=1200, height=600, startx=None, starty=None)
#used to find the height of what the screen size is so I could figure out
what it was set at.
"""print(turtle.window_width())
print(turtle.window_height())"""
#gives our wonderful circle a home (where it starts), to the right and
middle of the box
#old code (turtle.setworldcoordinates(-20, -20, 0, 20))
cassy.hideturtle()
cassy.penup()
cassy.goto(580, 0)
#sets the turtle to be facing left
cassy.left(180)
cassy.showturtle()
cassy.pendown()
#as always, I gotta have that sweet sweet starting message.
print("Welcome to the line generator!")
print("To start, type in a letter")
#using a dictionary function so I can assign each character a "Line"
line = {
"a" : "cassy.left(20)",
"b" : "cassy.forward(20)",
"c" : "cassy.right(45)",
"d" : "cassy.right(70)",
"e" : "cassy.circle(10)",
"f" : "cassy.left(15)",
"g" : "cassy.forward(15)",
"h" : "cassy.left(60)",
"i" : "cassy.forward(10)",
"j" : "cassy.forward(55)",
"k" : "cassy.circle(50, 100)",
"l" : "cassy.right(80)",
"m" : "cassy.forward(35)",
"n" : "cassy.left(75)",
"o" : "cassy.forward(45)",
"p" : "cassy.right(5)",
"q" : "cassy.forward(100)",
"r" : "cassy.right(65)",
"s" : "cassy.forward(125)",
"t" : "cassy.left(25)",
"u" : "cassy.forward(150)",
"v" : "cassy.right(95)",
"w" : "cassy.forward(120)",
"x" : "cassy.circle(25, 175)",
"y" : "cassy.circle(5, 190)",
"z" : "cassy.forward(175)",
"0" : "cassy.right(20)",
"1" : "cassy.forward(210)",
"2" : "cassy.left(120)",
"3" : "cassy.forward(115)",
"4" : "cassy.forward(15)",
"5" : "cassy.circle(30, 150)",
"6" : "cassy.left(70)",
"7" : "cassy.right(40)",
"8" : "cassy.backward(30)",
"9" : "cassy.backward(130)"
}
#let's the user type in letters/numbers (and only those (unless I want to
mix things up; we'll see))
while True:
draw = input("Type anything to draw! ")
#if statement to make sure that they only type in numbers or letters
if(draw.isalnum() == True):
#I can only assume that this executes the code inside the quotes
#but I haven't looked too deeply into what exec() does
exec(line.get(draw))
#this seperates each character drawn by a space, for funsies (yes I know it's a weird thing to say)
cassy.penup()
cassy.forward(15)
cassy.pendown()
#else statement in case they type in other charaters that aren't numbers or letters
else:
print("Please only use letters or numbers.")
好了,所以我知道这是一个很多的阅读,但我真正的问题是这行代码
exec(line.get(draw))
到目前为止,当我在1个字母同时键入程序才有效。但如果我尝试并键入多个字母,比如那句“你好”它给了我这个错误
Traceback (most recent call last):
File "C:/Users/73059/Final Project/Final Project funstuffs.py", line 87, in <module>
exec(line.get(draw))
TypeError: exec() arg 1 must be a string, bytes or code object
我真的不知道了很多关于函数的exec(),我已经一直在试图看看它的东西,这是一个项目,我真的没有太多时间。
如果有任何问题,或者你不明白我想完成什么,请告诉我。我有点绝望。
感谢
你的问题是不是真的与exec
电话,但与价值你传递作为参数。当您执行line.get(draw)
时,可以在line
字典中查找变量draw
的值。如果该值不存在(因为draw
是多字符字符串,则不会),则会得到None
。运行exec(None)
会为您提供TypeError
。
我有几种解决此问题的方法。你想要遵循哪些可能取决于你的程序需要什么样的行为。
首先,我建议使用括号索引字典,而不是get
方法。这会将您从TypeError
(从exec
)得到的错误更改为字典中的KeyError
。这仍然是一个例外,但它至少可以更准确地指出问题的原因(查找的字符串不在字典中)。
下一个建议是在尝试查找它之前检查多字符字符串,并向用户报告错误。你可以检查len(draw)
是否等于1
,如果是的话只运行其余的代码。我会将这张支票放在您当前对字母数字字符进行检查的地方。
下面是这两个补丁会是什么样在一起:
while True:
draw = input("Type anything to draw! ")
if draw.isalnum() and len(draw) == 1: # check length, "== True" and parens were unneeded
exec(line[draw]) # use indexing instead of "get" to generate better exception types
else:
print("Please only enter a single letter or number at a time.")
另外,如果你想允许更长的输入(与输入的每个字符被另案处理),你可以在你的代码改过来循环而不是试图一次性处理它们。这将是这个样子:
while True:
draw = input("Type anything to draw! ")
if draw.isalnum(): # no length check needed in this version
for character in draw: # loop over characters
exec(line[character])
cassy.penup() # it's not clear if you want these lines inside the inner loop
cassy.forward(15) # if not, you can unindent them one level
cassy.pendown()
else:
print("Please only use letters or numbers.")
虽然这应该工作,使用exec
通常是编写代码一个糟糕的方式。更好的方法是将函数(或其他可调用对象)放入字典中,然后调用从索引中返回的值。您可以使用lambda
关键字创建匿名功能。 Lambda函数有一些限制,但它们足够满足我们的需求。下面是你可能会看在字典中使用lambda表达式:
line = {
"a" : lambda: cassy.left(20),
"b" : lambda: cassy.forward(20),
"c" : lambda: cassy.right(45),
"d" : lambda: cassy.right(70),
"e" : lambda: cassy.circle(10),
"f" : lambda: cassy.left(15),
"g" : lambda: cassy.forward(15),
"h" : lambda: cassy.left(60),
"i" : lambda: cassy.forward(10),
"j" : lambda: cassy.forward(55),
"k" : lambda: cassy.circle(50, 100),
"l" : lambda: cassy.right(80),
"m" : lambda: cassy.forward(35),
"n" : lambda: cassy.left(75),
"o" : lambda: cassy.forward(45),
"p" : lambda: cassy.right(5),
"q" : lambda: cassy.forward(100),
"r" : lambda: cassy.right(65),
"s" : lambda: cassy.forward(125),
"t" : lambda: cassy.left(25),
"u" : lambda: cassy.forward(150),
"v" : lambda: cassy.right(95),
"w" : lambda: cassy.forward(120),
"x" : lambda: cassy.circle(25, 175),
"y" : lambda: cassy.circle(5, 190),
"z" : lambda: cassy.forward(175),
"0" : lambda: cassy.right(20),
"1" : lambda: cassy.forward(210),
"2" : lambda: cassy.left(120),
"3" : lambda: cassy.forward(115),
"4" : lambda: cassy.forward(15),
"5" : lambda: cassy.circle(30, 150),
"6" : lambda: cassy.left(70),
"7" : lambda: cassy.right(40),
"8" : lambda: cassy.backward(30),
"9" : lambda: cassy.backward(130)
}
while True:
draw = input("Type anything to draw! ")
if(draw.isalnum() == True):
for character in draw: # loop over characters
line[character]() # call the value looked up in the dict
cassy.penup() # it's not clear if you want these lines inside the inner loop
cassy.forward(15) # if not, you can unindent them one level
cassy.pendown()
else:
print("Please only use letters or numbers.")
还有其他几种方法,你可以使可调用,如使用functools.partial
乌龟方法及其自变量绑定在一起。
感谢您的反馈和帮助,我的项目现在运行顺利。 – Benita