0

I have the following function with using *args, and a lambda function:

def draw_figures(picture: Picture, *figures: Figure):
    # draws the figures on the picture
    ...

figures = [figure1, figure2, figure3]

draw_fun = lambda new_picture: draw_figures(new_picture, *figures)

As you can see, this code produces a draw_fun that I can call later, giving it a picture to draw the figures I already selected on it. I was wondering if I could do a similar thing with partial functions:

import functools

draw_fun = functools.partial(draw_figures, *figures)
draw_fun(other_picture)

Unfortunately, the latter does not work, because then draw_figures will take the first figure as the picture. This is coherent with the python documentation, since in partial, positional arguments provided to the new function are appended to the ones provided when defining the partial (check below). Is there a way of achieving what I am trying to do using partial?

# from python doc
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
ledermauss
  • 307
  • 1
  • 2
  • 13

1 Answers1

0

There's little benefit to use *figures in your original definition in the first place. Change it to

# You might want to use something more general for figures than list,
# like collections.abc.Sequence or collections.abc.Iterable
def draw_figures(picture: Picture, figures: list[Figure]):
    ...


figure_list = [figure1, figure2, figure3]

draw_fun = lambda new_picture: draw_figures(new_picture, figure_list)

Now you can simply specify the figures as a keyword argument when you use partial.

draw_fun = partial(draw_figures, figures=figure_list)

If draw_figures is a function whose signature you cannot change, I believe you are out of luck. Anything you would need to do to adapt it would be as much work as just avoiding partial in the first place.

chepner
  • 497,756
  • 71
  • 530
  • 681