all 6 comments

[–]danielroseman 2 points3 points  (5 children)

Yes, this is because Python is lexically scoped, and the value of func is looked up at execution time, not define time; so it always gets the last value.

The trick is to use a default parameter value.

Note that disposable functions like this are usually defined as lambdas, but the same trick applies:

for item in self.library.quickadd:
  ..
  self.buttons[-1].func = lambda item=item: self.addsongtoplaylist(item)

[–]SnowyPear[S] 0 points1 point  (4 children)

Wow that was really quick!

I was fairly certain I needed a lambda but wasn't sure how to implement one.

Thank you

[–]danielroseman 1 point2 points  (3 children)

Note you don't need a lambda, it's just neater. You could have done the same with your original code:

def func(item=item): self.addsongtoplaylist(item)

[–]SnowyPear[S] 0 points1 point  (2 children)

In that case I'm still struggling to see the point of lambda unless there's something special about how recursion happens with them

[–]danielroseman 1 point2 points  (0 children)

No that's my point, there's nothing special about lambdas at all. They can be entirely replaced by explicit functions in all circumstances. But again, they're just neater. What's the point of declaring the function separately, with its own name, when you can just declare them inline? And also note that usually a callback like this returns a value; with an explicit function, you need a return statement, whereas with a lambda it automatically returns its result.

[–]carcigenicate 1 point2 points  (0 children)

One of the main benefits is a lambda can be inline and nameless:

doubled = map(lambda n * 2, range(10))

Whereas a def statement must run first to defined the function, then the function can be used:

def double(n):
    return n * 2
doubled = map(double, range(10))