1

I want to set colors of an object, and don't want to create 10 functions for every color. So, I just want to declare the colors and create 10 buttons and one function. Error message is:

<lambda>() missing 1 required positional argument: 'green'

The code:

from tkinter import *

green=["#5bd575","#55c76d"]
#different colors should follow here

root=Tk()
Btn=Button(text="Trigger lambda", command=lambda green: printfunction(green))
Btn.pack()

def printfunction(colorset):
    print(colorset)

It does not need to be a lambda function, the question is just, How can I call the printfunction with an argument by clicking the button?

2
  • I found a way, but it is not totally convenient to me: command=self.start_set_color function, which calls a function for each color (2 lines) that calls a second, general function "self.set_color" (that gets the color as parameter. but still more than one function Commented May 19, 2013 at 11:53
  • found a solution, similar to the first idea with lambda: command=lambda:set_color("green") for the green-button. lambda just has to be called without the parameter. feeling kind of stupid. Commented May 19, 2013 at 12:08

2 Answers 2

2

The command callable doesn't take any arguments. If you want to pass the green list into printfunction, just omit the argument, the lambda doesn't need it:

Btn=Button(text="Trigger lambda", command=lambda: printfunction(green))

Now green inside the lambda refers to the global.

If all you wanted to do was to call printfunction with a pre-defined argument, you could use the functools.partial() function; you pass it the function to be called plus any arguments that need to be passed in, and when it's return value is called, it'll do exactly that; call the function with the arguments you specified:

from functools import partial

Btn=Button(text="Trigger lambda", command=partial(printfunction, green))
Sign up to request clarification or add additional context in comments.

9 Comments

Alternatively, you can use partial(printfunction, green)
@JakubM.: I fear that explaining functools.partial() is going to be a conceptual step too far.
functools.partial() is the right tool for the job here - no point reinventing the wheel. I think if you get lambda, you'll get partial().
Oh you guys and your arm twisting. partial() is indeed the right tool, it is more performant than a lambda. It is the right tool when you know what you are doing, but when you are still grasping the concepts of callables and Tk buttons having to learn about partials too is extra cognitive weight that a new learner could do without. But, on your heads be it. :-P
@Bakuriu: That is nothing special about lambdas, that happens to functions too. Partials have no scoped namespace themselves and are thus not affected, sure, but you are not defining a function or lambda there. What you see is a misunderstanding about when a name in a new scope is looked up. lambdas.append(lambda x=x: x+1) will print 1 then 2.
|
0

Python is incredibly dynamic, you can modify classes after their definition or create local functions. Example:

class X:
    # generic print function
    def print_color(self, color):
        pass

# dictionary with colors to support
COLORS = {'green': ["#5bd575","#55c76d"]}

# attach various print functions to class X
for name, value in COLORS.items():
    def print_color_x(self, value=value):
        self.print_color(value)
    setattr(X, 'print_color_{}'.format(name), print_color_x)

Note the value=value default parameter. This one is necessary to bind the value within each iteration. Without it, the lookup of value would take place when the function is called, giving you errors about a missing global value or picks up a random one that it happens to find there, but not the one you want. Using functools.partial() could be cleaner, if it allowed creating proper memberfunctions and not just staticfunctions. Note that the example pure Python implementation mentioned in the documentation allows creating memberfunctions, so using that as a replacement is an option.

2 Comments

( : well, I upvoted your solution because it is simple and easy, but I wouldn't spare the upcoming Pythonista another relatively simple option where you learn a bit more about Python. Next step: Overriding getitem to generate the colour-printing methods on the fly.
hm interesting idea. in some other peace of code i noticed a strange behaviour where values had been picked randomly, looks like the value=value thing is the way to go there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.