提问人:Akash Singh 提问时间:10/31/2023 最后编辑:Akash Singh 更新时间:11/1/2023 访问量:57
在python中按不同的键由不同的对象调用相同的函数
Calling same function by different objects by pressing different key in python
问:
我使用 turtle 模块在 python 中创建了两个,分别说“tur1”和“tur2”。我在屏幕上创建了事件侦听器。我创建了一个函数“move_fwd(turte_name)”,它将向前移动 20 步。
我希望如果按下键“w”,那么这个方法应该被“tur1”调用,tur1应该移动,如果按下键“i”,那么这个函数应该被“tur2”turtle调用,它应该移动。
我不知道如何在event_listener调用此方法时传递参数“turtle_name”。
from turtle import Turtle, Screen
screen = Screen()
tur1 = Turtle()
tur1.shape("turtle")
tur1.shape("turtle")
tur1.penup()
tur1.setposition(x=-200, y=-100)
tur2 = Turtle()
tur2.shape("turtle")
tur2.penup()
tur2.setposition(x=200, y=100)
def move_fwd(turtle_name):
turtle_name.forward(20)
screen.listen()
screen.onkey(move_fwd, "w") # how to tell that this is to be called for tur1
screen.onkey(move_fwd, "i") # how to tell that this is to be called for tur2
screen.exitonclick()
我有一些想法如何通过添加addEventListener在javascript中做到这一点。
document.addEventListener("keypress", function(event) {
makeSound(event.key);
buttonAnimation(event.key);
});
function makeSound(key) {
switch (key) {
case "w":
var tom1 = new Audio("sounds/tom-1.mp3");
tom1.play();
break;
case "a":
var tom2 = new Audio("sounds/tom-2.mp3");
tom2.play();
break;
case "s":
var tom3 = new Audio('sounds/tom-3.mp3');
tom3.play();
break;
但是不知道如何在 python 中做。
感谢您的宝贵时间。
答:
您只需要调用两个不同的函数:
def move_fwd1():
tur1.forward(20)
def move_fwd2():
tur2.forward(20)
...
screen.onkey(move_fwd1, "w") # how to tell that this is to be called for tur1
screen.onkey(move_fwd2, "i") # how to tell that this is to be called for tur2
使用lambda
screen.onkey(lambda: move_fwd(tur1), "w")
screen.onkey(lambda: move_fwd(tur2), "i")
评论
lambda
这个答案是由 Barmar 的评论触发的,他解释了使用该结构的优点:lambda
@Claudio 这种方法比为每只定义一个命名函数更能概括。
我建议使用另一种方法进行泛化,该方法允许使用 Python 列表定义任意数量的海龟及其属性,然后用于生成提供所需功能所需的代码。是的,下面的代码对不同的键盘键使用不同的函数名称,但同时也允许修改用于所有海龟的函数。move()
from turtle import Screen, Turtle
screen = Screen()
Turtles = [Turtle(), Turtle() ]
StartPositions = [(200,-100),(200,100) ]
Names = ["turti_1", "turti_2" ]
Keys = ["w", "i" ]
Colors = ["red", "green" ]
# =========================================================
def move(turtle):
print(turtle.name)
turtle.forward(20)
for turtleNo, turtle in enumerate(Turtles):
turtle.shape("turtle")
turtle.penup()
turtle.setposition(StartPositions[turtleNo])
turtle.name=Names[turtleNo]
turtle.color(Colors[turtleNo])
exec(f'def onKey_{Keys[turtleNo]}(): move(Turtles[{turtleNo}])')
exec(f'screen.onkey(onKey_{Keys[turtleNo]}, "{Keys[turtleNo]}")')
screen.listen()
screen.exitonclick()
在某些情况下,有意义并且有助于实现泛化,从而可以将字符串变量用于变量名称或变量名称的一部分,同时将它们用作字符串。exec()
将上述代码中的列表扩展为:
Turtles = [Turtle() , Turtle() , Turtle() , Turtle() , Turtle() ]
StartPositions = [(200,-100) , (200,100) , (200,-50) , (200,50) , (200,0) ]
Names = ["turti_1" , "turti_2" , "turti_3" , "turti_4" , "turti_5" ]
Keys = ["w" , "i" , "s" , "k" , "b" ]
Colors = ["red" , "green" , "blue" , "cyan" , "magenta" ]
并享受五只海龟比赛......
评论
lambda
您在这里面临的来自 javascript 编程的实际问题是 Python 模块,可能是为了简单起见,或者根本没有充分的理由,没有将触发键盘事件处理函数的键传递给此函数,因为它通常是所有键盘输入处理支持模块的标准。
这不是 Python 本身的问题。它仅特定于 turtle.py 模块。turtle.py
我建议你阅读 ggorlen 对另一个问题的回答:
序言:是一团糟,对初学者来说并不像它可能的那样友好。API 中存在大量不一致之处,它几乎违反了 Python 禅宗的所有规则。可能是因为它是很久以前写的,从那以后没有太大变化。因此,当 turtle API 或内部的某些部分莫名其妙地奇怪或不一致,或者 IDE 自动完成变得混乱时,请不要太惊讶。
您可以自己体验修补 turtle 模块,如下面的代码所示,只更改模块中的一行(以便使按下的键可用作参数)以实现您有充分理由期望的功能:turtle.py
# The PATCH:
from turtle import TurtleScreenBase
def _onkeyrelease(self, fun, key):
"""Bind fun to key-release event of key.
Canvas must have focus. See method listen
"""
if fun is None:
self.cv.unbind("<KeyRelease-%s>" % key, None)
else:
def eventfun(event):
fun(key) # <<<=== CHANGED ===>>> was: fun()
self.cv.bind("<KeyRelease-%s>" % key, eventfun)
TurtleScreenBase._onkeyrelease = _onkeyrelease
# The script utilizing the PATCH:
from turtle import Turtle, Screen
screen = Screen()
tur1 = Turtle()
tur1.shape("turtle")
tur1.shape("turtle")
tur1.penup()
tur1.setposition(x=-200, y=-100)
tur2 = Turtle()
tur2.shape("turtle")
tur2.penup()
tur2.setposition(x=200, y=100)
def onKey(key):
if key=="i":
print(" i pressed. Moving tur1 .")
tur1.forward(20)
if key=="w":
print(" w pressed. Moving tur2 .")
tur2.forward(20)
screen.listen()
screen.onkey(onKey, "w") # how to tell that this is to be called for tur1
screen.onkey(onKey, "i") # how to tell that this is to be called for tur2
screen.exitonclick()
评论