为什么这种使用Python中的Turtle模块检测按键的方法不起作用?
Why does this method of detecting keypresses with the Turtle module in Python not work?
已阅读...
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 = 500, 500
screen = Screen()
screen.setup(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')
而不是调用函数和 returns None
这不是函数。
您可以像这样使用 lambda
创建自己的函数:
screen.onkey(lambda :check('a'), 'a')
而如果你想为字母表中的每个字母调用 onkey()
,那么你可以很容易地有一个循环,但不会陷入 问题:
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')
。这意味着您正在传递 return check
函数的值,而不是函数本身。
您的检查函数在 return 值中没有任何 return
语句。在 Python 中,不 return 显式 return 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
函数创建了一个新函数,其中原始函数的一些参数已被“锁定”。
已阅读...
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 = 500, 500
screen = Screen()
screen.setup(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')
而不是调用函数和 returns None
这不是函数。
您可以像这样使用 lambda
创建自己的函数:
screen.onkey(lambda :check('a'), 'a')
而如果你想为字母表中的每个字母调用 onkey()
,那么你可以很容易地有一个循环,但不会陷入
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')
。这意味着您正在传递 return check
函数的值,而不是函数本身。
您的检查函数在 return 值中没有任何 return
语句。在 Python 中,不 return 显式 return 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
函数创建了一个新函数,其中原始函数的一些参数已被“锁定”。