Sep-03-2021, 06:32 PM
(This post was last modified: Sep-03-2021, 10:55 PM by deanhystad.)
The only way I could get your code to raise and index out of range error is put an empty list or tuple in l_credentials.
I would write your example like this:
There are two ways to get around this: You can use partial from the functools library, or you can use default arguments in your lambda expression. In this example the lambda expression creates an argument named "arg" and assigns it the default value of l_credentials[i][0] for the CURRENT value of i.
I would write your example like this:
for creds in self.l_credentials: if len(creds> 0): self.my_users.add_command(creds[0], command=lambda arg=creds[0]: self.callback(arg))Are you skipping the first credential on purpose? This starts at l_credentials[1], the second credential.
for i in range(1, len(self.l_credentials))Do you want to bind all commands in my_users to the last user. That is what you are doing with this lambda expression.
self.my_users.add_command(label="{}".format(self.l_credentials[i][0]), command=lambda: self.callback(self.l_credentials[i][0]))See this example for proof. It looks like it should print "admin" , "Cheese", "Milk".
l_credentials = [('admin', '999'), ('Cheese', 'incorrect'), ('Milk', 'Cookies')] funcs = [lambda: print(l_credentials[i][0]) for i in range(len(l_credentials))] for func in funcs: func()
Output:Milk
Milk
Milk
My list comprehension makes a list of functions that call print(l_credentials[i][0]) and that is the problem. When I execute my functions, i == 2, and each function in my comprehension is evaluated as print(l_credentials[2][0]) Your code will do the same. If you have 10 l_credentials, every command will call self.callback(self.l_credentials[9][0]).There are two ways to get around this: You can use partial from the functools library, or you can use default arguments in your lambda expression. In this example the lambda expression creates an argument named "arg" and assigns it the default value of l_credentials[i][0] for the CURRENT value of i.
l_credentials = [('admin', '999'), ('Cheese', 'incorrect'), ('Milk', 'Cookies')] funcs = [lambda arg=l_credentials[i][0]: print(arg) for i in range(len(l_credentials))] for func in funcs: func()
Output:admin
Cheese
Milk
This works because each of my lambdas has a different default value for the first argument. If we could peek into the lamda, you would see:funcs = [lambda: print('admin'), lambda: print('Cheese'), lambda: print('Milk')Note that this works just like a default argument. If an argument value is provided in the function call, the default value is overwritten.
l_credentials = [('admin', '999'), ('Cheese', 'incorrect'), ('Milk', 'Cookies')] funcs = [lambda arg=l_credentials[i][0]: print(arg) for i in range(len(l_credentials))] for func in funcs: func('All the same again')
Output:All the same again
All the same again
All the same again