Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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?

share|improve this question
    
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 –  user2366975 May 19 '13 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. –  user2366975 May 19 '13 at 12:08

2 Answers 2

up vote 1 down vote accepted

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))
share|improve this answer
1  
Alternatively, you can use partial(printfunction, green) –  Jakub M. May 19 '13 at 11:13
    
@JakubM.: I fear that explaining functools.partial() is going to be a conceptual step too far. –  Martijn Pieters May 19 '13 at 11:15
1  
One day he will appreciate... –  Jakub M. May 19 '13 at 11:17
2  
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 –  Martijn Pieters May 19 '13 at 11:25
1  
@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. –  Martijn Pieters May 19 '13 at 11:57

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.

share|improve this answer
1  
Now you are just muddying the waters some more.. –  Martijn Pieters May 19 '13 at 11:59
    
( : 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. –  Ulrich Eckhardt May 19 '13 at 12:11
    
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. –  user2366975 May 19 '13 at 23:14

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.