Reputation: 667
I tried myself at making the Pong project using the turtle package on Python.
I know how to make the code work (using 4 different functions taking no arguments, for each paddle and directions), but my question is if and how can I do it with this idea.
Here's the code I'm attempting to make work :
def move_paddle_up(paddle):
y = paddle.ycor()
y += 20
paddle.sety(y)
def move_paddle_down(paddle):
y = paddle.ycor()
y -= 20
paddle.sety(y)
#Keyboard binding movement
screen.listen()
screen.onkeypress(move_paddle_up(left_pad), "w")
screen.onkeypress(move_paddle_down(left_pad), "s")
screen.onkeypress(move_paddle_up(right_pad), "Up")
screen.onkeypress(move_paddle_down(right_pad), "Down")
When the screen is launched, the paddles won't move if I press the associated keys.
With the way of using the 4 different functions, it works.
It's just that I am curious to know how I should call or define the arguments in such a function.
Upvotes: 1
Views: 1085
Reputation: 41905
I see then that is it quite more work than just creating 4 functions.
I think you got the wrong take home message. @BehdadAbdollahiMoghadam's use of functools.partial()
is spot on, but we can fit it into your existing code with less overhead:
from functools import partial
# ...
def move_paddle_up(paddle):
paddle.sety(paddle.ycor() + 20)
def move_paddle_down(paddle):
paddle.sety(paddle.ycor() - 20)
# Keyboard binding movement
screen.onkeypress(partial(move_paddle_up, left_pad), "w")
screen.onkeypress(partial(move_paddle_down, left_pad), "s")
screen.onkeypress(partial(move_paddle_up, right_pad), "Up")
screen.onkeypress(partial(move_paddle_down, right_pad), "Down")
screen.listen()
# ...
Upvotes: 1
Reputation: 1665
The onkeypress
method doesn't allow to pass a function with arguments, however you can use functools.partial
for this kind of situations.
You can create a function which handles all type of keyboard presses, and pass that function as a partial function
.
Let's create that function first:
def move_paddle(paddle, key_pressed):
def move_paddle_up(paddle):
y = paddle.ycor()
y += 20
paddle.sety(y)
def move_paddle_down(paddle):
y = paddle.ycor()
y -= 20
paddle.sety(y)
if paddle == left_pad:
if key_pressed == "w":
move_paddle_up(paddle)
elif key_pressed == "s":
move_paddle_down(paddle)
elif paddle == right_pad:
if key_pressed == "Up":
move_paddle_up(paddle)
elif key_pressed == "Down":
move_paddle_down(paddle)
Now we can use this function with functools.partial
:
import functools
[...]
screen.onkeypress(functools.partial(move_paddle,[left_pad,"w"]), key="w")
screen.onkeypress(functools.partial(move_paddle,[left_pad,"s"]), key="s")
screen.onkeypress(functools.partial(move_paddle,[right_pad,"Up"]), key="Up")
screen.onkeypress(functools.partial(move_paddle,[right_pad,"Down"]), key="Down")
The way functools.partial
works:
It takes a function
with some arguments
(*args, it's actually an unpacked list), and then creates a new function which is the previous function that gets those args as input:
def partial(func, /, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = {**keywords, **fkeywords}
return func(*args, *fargs, **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc
Upvotes: 1