如何解决为什么这种使用 Python 中的 Turtle 模块检测按键的方法不起作用?
已阅读...
How can I log key presses using turtle?
我正在尝试使用稍微不同的方法检测按键。
这是我的代码的简化版本,它按预期工作...
from turtle import *
WIDTH,HEIGHT = 500,500
screen = Screen()
screen.setup(WIDTH,HEIGHT)
bgcolor('grey')
ht()
pu()
def checka():
write('a')
fd(10)
def checkb():
write('b')
fd(10)
screen.onkey(checka,'a')
screen.onkey(checkb,'b')
screen.listen()
screen.mainloop()
但是我希望处理所有字母的按键,所以尝试了这个...
from turtle import *
WIDTH,HEIGHT)
bgcolor('grey')
ht()
pu()
def check(l):
write(l)
fd(10)
screen.onkey(check('a'),'a')
screen.onkey(check('b'),'b')
screen.listen()
screen.mainloop()
但是这段代码不起作用。 任何人都可以对这里发生的事情有所了解,或者提出一种替代(但同样简单)的方法来实现相同的目标吗?
解决方法
我猜 screen.onkey()
需要一个它调用的函数。
您的代码:screen.onkey(check('a'),'a')
改为调用函数并返回 None
,它不是函数。
您可以像这样使用 lambda
创建自己的函数:
screen.onkey(lambda :check('a'),'a')
如果您想为字母表中的每个字母调用 onkey()
,那么您可以轻松地进行循环,但不会陷入 scope 问题:
import string
for c in string.ascii_lowercase:
screen.onkey(lambda c=c:check(c),c)
,
screen.onkey()
函数需要一个函数作为输入。在您的第一个示例中,您正确执行此操作 (screen.onkey(checka,'a')
),但在第二个示例中,您在传递它之前调用该函数 (screen.onkey(check('a'),'a')
。这意味着您正在传递 返回值 check
函数,而不是函数本身。
您的检查函数中没有任何 return
语句明确返回值。在 Python 中,不显式返回值的函数返回 None
。所以你实际上是在调用 screen.onkey(None,'a')
,我猜这没有任何效果。
要解决此问题,您可以使用闭包 - 函数内的函数。使用闭包,内部函数可以使用外部函数可用的变量,这意味着您可以为任何字母创建检查函数。
def make_check_func(l):
def check():
write(l)
fd(10)
return check
screen.onkey(make_check_func('a'),'a')
screen.onkey(make_check_func('b'),'b')
或者,正如 quamrana 所建议的,您可以使用 lambda 函数以更少的代码完成同样的事情。
def check(l):
write(l)
fd(10)
screen.onkey(lambda: check('a'),'a')
screen.onkey(lambda: check('b'),'b')
--编辑--
要为字母表中的所有字母添加函数,您可以使用 for 循环。方便的是,Python 已经在 string.ascii_lowercase 处定义了一个包含所有小写 ASCII 字符的字符串,因此我们可以使用它来循环。
import string
def make_check_func(l):
def check():
write(l)
fd(10)
return check
for l in string.ascii_lowercase:
screen.onkey(make_check_func(l),l)
这里,for 循环的主体将针对字符串中的每个字符运行一次,l
的值将是该字符。这具有运行 screen.onkey(make_check_func('a'),'a')
,然后 screen.onkey(make_check_func('b'),'b')
,一直到 screen.onkey(make_check_func('z'),'z')
的效果。
请注意,在 for 循环中使用 screen.onkey(lambda: check(l),l)
将不起作用,因为 lambda 函数“记住”的 l
的值将始终为“z”。有关说明,请参阅 common gotchas 条目。
虽然这可以使用@quamrana 演示的 lambda
解决,或者使用 @JackTaylor 详细解释的闭包来解决,但我偏爱 partial
解决此类问题:
from turtle import Screen,Turtle
from string import ascii_letters
from functools import partial
WIDTH,HEIGHT = 500,500
def check(letter):
turtle.write(letter)
turtle.forward(10)
screen = Screen()
screen.setup(WIDTH,HEIGHT)
screen.bgcolor('grey')
turtle = Turtle()
turtle.hideturtle()
turtle.penup()
for letter in ascii_letters:
screen.onkey(partial(check,letter),letter)
screen.listen()
screen.mainloop()
partial
函数创建了一个新函数,其中原始函数的某些参数已被“锁定”。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。