0

Problem

As far as I'm aware, this undesired behaviour (by my standards) happens, because of late-binding in contrast to early binding in the loop. That is, when the lambda function is called, the iterator variables all have the same values, namely the ones after all loops are finnished.

for color in range(N_COLORS):
    for hsv in range(N_HSV):
        for mm in range(N_MINMAX):
            cv2.createTrackbar(STR_COLORS[color] + STR_HSV[hsv] + STR_MINMAX[mm], window_title, 0, 255, lambda x: change(color, hsv, mm, x))

Question

How can I rewrite this code, so that each Trackbar that is created, has distinct values for color, hsv and mm instead of all of them having the same value.

Minimal Working Example:

import numpy as np

N_COLORS = 3
N_HSV = 3
N_MINMAX = 2

list = []


for color in range(N_COLORS):
    for hsv in range(N_HSV):
        for mm in range(N_MINMAX):
            list.append(lambda: print(color, hsv, mm))
            
list[0]()
list[1]()
list[2]()

expected output:
[0, 0, 0]
[0, 0, 1]
[0, 1, 0]

actual output:
[2, 2, 1]
[2, 2, 1]
[2, 2, 1]

Answer

As per the duplicate, this solves it

cv2.createTrackbar(STR_COLORS[color] + STR_HSV[hsv] + STR_MINMAX[mm], window_title, 0, 255, lambda x, color=color, hsv=hsv, mm=mm: change(color, hsv, mm, x))
infinitezero
  • 1,610
  • 3
  • 14
  • 29
  • Not mentioned in the duplicate, but I think `functools.partial` would be a better fit here: `partial(change, color, hsv, mm)` instead of a lambda expression. – chepner Jan 05 '23 at 22:23

0 Answers0