Python Forum
Python Error List Index Out of Range - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Python Error List Index Out of Range (/thread-34819.html)



Python Error List Index Out of Range - abhi1vaishnav - Sep-03-2021

I am making a program using python and tkinter which basically is an expense tracking system. However, I am getting an error when running my program which has to do with the code shown below. It is raising an error, mentioning that the 'list index is out of range.'

It confuses me that I am getting this error because the for loop (in this case) runs only once and the index seems to be within range as the value of 'i' is 1 and the list that it is iterating through is as follows: [('admin', '999'), ('Cheese', 'incorrect')] Would anyone please be able to explain why I am getting this error...

        for i in range(1, len(self.l_credentials)):
            print(i)
            print(self.l_credentials)
            self.my_users.add_command(label="{}".format(self.l_credentials[i][0]), command=lambda: self.callback(self.l_credentials[i][0]))
            self.my_users.add_separator()



RE: Python Error List Index Out of Range - buran - Sep-03-2021

index start at 0 and thus max index value is len(self.l_credentials)-1
However, check this https://python-forum.io/thread-362.html

Also, always post full traceback you get, in error tags, not just the last line


RE: Python Error List Index Out of Range - deanhystad - Sep-03-2021

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:
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



RE: Python Error List Index Out of Range - abhi1vaishnav - Sep-03-2021

Awesome, this solved my problem! I appreciate it, thanks! Also, sorry for forgetting to include the tags for my code, if that is what you're referring to, but I am not sure how to do that