3

I have a python program in pyqt with a button with the follwoing:

this=[1,k]   
button.clicked.connect(lambda x=this:self.testFunction(str(x)))

When I press the button I get testFunction(False) rather testFunction(str([1,k])). Any ideas why? Thanks in advance.

3
  • Does the problem remain if you change this to, say, these on both lines? (This will either fix the problem or disprove the hypothesis that something is setting this to False between the first line and the second.) Commented Sep 16, 2013 at 20:07
  • I got it working with the following: self.connect(button,QtCore.SIGNAL("clicked()"),lambda x=this:self.testFunction(str(x))) Commented Sep 16, 2013 at 20:10
  • 1
    I've never used qt, but here's my guess: lambdas you use for event binding ought to have event for a first argument: button.clicked.connect(lambda event, x=this: self.testFunction(str(x))) Commented Sep 16, 2013 at 20:16

2 Answers 2

7

The reason is that you are misinterpretting how lambda works. Lambda returns an anonymous function with the definition you give it. By saying lambda x=this: you are saying if the call to this function doesn't have an x argument default to use this instead.

Observe:

l = lambda x=3: x*2
print l(10)  # Prints 20
print l()    # Prints 6

If we check the documentation for QPushButton.clicked() (inherited from QAbstractButton), we see that it fires with a boolean argument.

So in this line:

button.clicked.connect(lambda x=this:self.testFunction(str(x)))

The lambda function always gets passed an argument, which is passed from QPushButton.clicked() and will be either True or False. Hence the default of this is never used. As an alternate you could use:

button.clicked.connect(lambda x:self.testFunction(str(this)))

But that isn't probably what you want, as it will always pass the string variant of the array this to the function. On the other hand this:

button.clicked.connect(lambda x:self.testFunction(str(this[x])))

Will pass the string casting of their 1 or k depending on whether the passed argument is True or False.

Sign up to request clarification or add additional context in comments.

1 Comment

One item missing from this (very useful) answer: you can completely ignore the boolean value using: button.clicked.connect(lambda ignore, x = this : self.testFunction(str(x))). The boolean value gets assigned to ignore (and is ignored) and x (i.e., this) is properly used as the argument of the function.
1

I was having a similar problem but the lambda didn't accept the ignore nor checked and I was getting an error that the lambda was missing a positional argument. I don't know if this is the right thing, but it worked for me. I fixed by assigning checked=True

button.clicked.connect(lambda checked=True, x=this:self.testFunction(str(x)))

1 Comment

This just worked for me. Thank you so much!

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.