IndexError: list assignment index out of range Python 3 - python

Someone has a Idea why i get an IndexError in this code?
global gegner
global gegnerhp
gegner = []
gegberhp = []
for i in range(1,anzahlgegner):
random = randint(1,5)
if random == 1:
gegner[i] = "goblin"
gegnerhp[i] = randint(10,50)
elif random == 2:
gegner[i] = "ghost"
gegnerhp[i] = randint(10,50)
elif random == 3:
gegner[i] = "hound"
gegnerhp[i] = randint(10,50)
elif random == 4:
gegner[i] = "wolf" #LINE 147
gegnerhp[i] = randint(10,50)
elif random == 5:
gegner[i] = "goblin"
gegnerhp[i] = randint(10, 50)
print("* {0} with {1} HP".format(gegner[i]),gegnerhp[i])
For example when random is 4 i get the following error:
File "C:/Users/Fabio/PycharmProjects/test\dungeon.py", line 147, in run
gegner[i] = "wolf"
IndexError: list assignment index out of range
Maybe my declaration of the list/arrays is wrong?...

There are a number of misconceptions here, and I don't think that addressing just the one you've specifically asked about will be properly helpful, so I'm going to do more than that.
First of all, lists. You're creating empty lists gegner and gegnerhp; it looks like you then want to add some items to those lists, and you're trying to do it by specifying an index. In python, the list index starts from 0, not 1.
i.e. in the following list:
>>> gegner = ["wolf", "hound", "goblin"]
>>> print(gegner[0])
wolf
>>> print(gegner[1])
hound
The index '1' is the second item in the list.
In your code, your range(1,anzhalgegner) would start at 1 and increment up to whatever you have set anzhalgegner to be. In your first iteration, your code attempts to assign a value to the list gegner at position 1 - however, the list does not have anything at position 0, meaning it can't assign anything to position 1.
The simplest change to get you started would be to start your range from 0.
Once you've tried that out, I would also suggest that instead of manually specifying what position in the list to place an item (list[index] = value), since all you are doing is adding things to the end of the list, consider using the append method. Then it would look something like this:
if random == 1:
gegner.append("goblin")
gegnerhp.append(randint(10,50))

You get an IndexError because the lists are empty.
You can't create list items by accessing invalid indices. Use .append isntead.
if random == 1:
gegner.append("goblin")
gegnerhp.append(randint(10, 50))
etc.

your lists gegner and gegnerhp are empty, thus accessing them will give you an error.

Related

Python | I'm getting an error when seeing if a list has an element or not

Hey so the other day I was messing around with some code and it gave me this error.
if clearargs[1] == "history":
\n IndexError: list index out of range
elif startswith(ui, "clear") or startswith(ui, "clr"):
clearargs = ui.split()
if len(clearargs) < 1:
refs.clearscr("Windows", os)
else:
if clearargs[1] == "history":
history = []
os.remove(hfilepath)
elif clearargs[1] == "exthistory":
extendedhistory = []
os.remove(ehfilepath)
btw most functions are custom defined
The list index starts from zero.
So, if the length of the list is exactly one, than clearargs[0] is the right access to the first value in the list.
When asking to get the value from clearargs[1], you assume that the length of the list is at least 2.
else block will be executed only when thelen(clearargs < 1) so the only valid index is clearargs[0].You are making a logical error.

Confused about list variable assignment

I'm following a book and i ran into this sample program. I'm not sure how the numbers[position] in line 5 is working here? What is the relationship between position and numbers in that variable assignment?
numbers = [1, 3, 5]
position = 0
while position < len(numbers):
number = numbers[position]
if number % 2 == 0:
print "Found even number", number
break
position = position + 1
else:
print "No even number found"
That number inside square brackets is an index of the list,
like so
lst = ["b", "c", 3] # Take care not to use "list" as a variable name by the way.
print lst[0] # I used lst in my example
gives you:
"b"
The first element of the list.
However I could not pass without saying that for loop is a far better way of doing this. Rather than incrementing position one-by-one and telling while loop to stop when it reaches to the length of the list is just good for understanding the concepts. I am sure your textbook is going to cover that next.
It's not variable assignment, it's lookup. position is an index; when it has a value of 0, numbers[position] returns 1 (the first element in numbers), for position 1 it gets 3, etc.
Python sequences like list are indexed 0-up, so the first element in a sequence is at index 0, and the last is at index len(seq) - 1.
In number = numbers[position] literally means what it says. position is a position in the list. First it is assigned to zero, so when doing numbers[position] it is actually calling the number in the list at position zero which is 1. Then it does position = position + 1 which will ask it for the number in position 1 in the list and so on.
I wasn't familiar with this style of variable assignment. I've seen lists referenced directly using index numbers. But since this post, I've tried the following and it cleared it up. Thank you very much!
list1 = ["apples", "oranges"]
position = 1
output1 = list1[0]
output2 = list1[position]
print output1
print output2

Removing objects from a list in python, Attribute error

I'm pretty much a complete beginner to python, and i'm having problems removing an integer from a list. I'm getting a error, AttributeError: 'int' object has no attribute 'remove', and i don't know how to fix it. This is probably really easy to experienced eyes, and I have looked at past answers but keep returning same error
repeat = 0
while repeat <= 4:
question_list = [1,2,3,4,5]
number = random.choice(question_list)
if number == 1:
print(question1())
repeat = repeat + 1
number.remove(1)
elif number == 2:
print(question2())
repeat = repeat + 1
number.remove(2)
elif number == 3:
print(question3())
repeat = repeat + 1
number.remove(3)
elif number == 4:
print(question4())
repeat = repeat + 1
number.remove(4)
elif number == 5:
print(question5())
repeat = repeat + 1
number.remove(5)
number = random.choice(question_list) assigns number to an int returned from calling random.choice on your question list. If you want to remove from question_list call remove on the list not number:
question_list.remove(x)
You need to assign question_list outside the while loop, if you put it inside you keep creating a new list so the remove never persists.
question_list = [1,2,3,4,5] # here
while repeat <= 4:
A nicer implementation may be to use a dict and just use range:
import random
# map numbers to functions
questions = {1:question1,2:question2,3:question3,4:question4,5: question5}
question_list = [1, 2, 3, 4, 5] # outside loop
for _ in range(4): # loop in range 4
number = random.choice(question_list)
question_list[func]() # call function using dict key val
question_list.remove(number)
Or simply store the functions in a list and randomly choose one:
question_list = [question1,question2,question3,question4,question5]
for _ in range(4):
func = random.choice(question_list)
func()
question_list.remove(func)
Since a comment already explained why your code doesn't work, I'd like to suggest a simpler alternative.
It seems like you have a few functions you want to call in a random order.
There is no need to complicate things the way you're doing it, and mess around with removing elements from the list.
You can simply have a list of functions, shuffle it, and call every function in order:
questions = [question1, question2, question3, question4, question5]
random.shuffle(questions)
for question in questions:
question()
You should use the remove function on the list, and give the int as a parameter. So it should become:
question_list.remove(something)
But be careful, because if there is no "something" you will get an error.

Simplifying a short list comparison

Here's the code. It's being used to change a certain value stored in a list (of between 25 and 81 values), depending on the user input. I'm using a second list to decide what happens, with only 4 values inside, which were also the user's input. Basically, if the user chooses a certain value, it changes to the next value in sequence.
if list1[value] == list2[3]:
list[value] = list2[0]
elif list1[value] == list2[0]:
list[value] = list2[1]
elif list1[value] == list2[1]:
list[value] = list2[2]
elif list1[value] == list2[2]:
list[value] = list2[3]
My problem is, I can't find a way to make it simpler. It looks quite long and ugly. It also needs to be executed many times based on extra inputs, so, if the user chose the same variable twice, it would change each time, in sequence.
This seems like such a dumb problem. I've been trying to think of how to simplify this for ages, to a short for loop or something, but for some reason fail every time.
I've tried something like this:
e = value % 4
if list1[value] == list2[e]:
list1[value] = list2[e + 1]
#This isn't exactly what I had, but something along these lines, maybe in a for loop too etc.
List 2 contains 4 string, [colour1, colour2, colour3, colour4]
List 1 contains these same strings, but looped over and over until it hits the list limit specified by user.
Thanks for any help!
Instead of a list for the "cycle" set of data, use a dictionary of {value: nextvalue}, i.e.:
cycler = {0: 1, 1: 2, 2: 3, 3: 0} # replace 0,1,2,3 with the actual values
if list1[value] in cycler:
list1[value] = cycler[list1[value]]
EDIT: To build the cycler from a list of elements:
cycler = {list2[i-1]: list2[i] for i in xrange(len(list2))}
# Note that this works because `list2[-1]` indexes the last element.
for i in range(0, len(list2):
if list1[value] == list2[i] :
list1[value] = list2[(i+1)%len(list2)]

Creating an empty list to have data assigned afterwards

Lets say that I want to create a list of names
listOfNames = []
Then I have a while loop such as
count = 0
while listOfNames[count] < 10:
nameList[count] = raw_input("Enter a name: ")
count += 1
Python says that the list index is out of range, but the list index should be at 0, correct?
How do add to the list each time the while loop is ran? I'm assuming something is wrong with my list assignment.
An empty list doesn't have any index yet, it's an empty list! If you want to fill it, you have to do something like this :
while count < 10:
nameList.append(raw_input("Enter a name: "))
count += 1
This way, your condition will be evaluated and with the append method, you will be able to add new items in your list.
There are a few advanced tricks to do this easily, but considering your level, I think it's better that you understand this code before moving on.
Most idiomatic is to use a list comprehension:
namelist = [raw_input("Enter a name: ") for i in range(10)]
(or use _ for i, although I personally wouldn't)
This has the advantage of creating the list on the fly, while having to use neither the append() method nor explicit indexing.
count = 0
while listOfNames[count] < 10:
nameList.append(raw_input("Enter a name: "))
count += 1
Use append for quick n easy...
Alternatively:
nameList[len(nameList):] = [raw_input("Enter a name: ")]
Edit: Did you mean listOfNames to be appended as opposed to nameList?
Your list assignment is right, your problem is with your use of indexes which do not yet exist.
count = 0
while listOfNames[count] < 10:
nameList[count] = raw_input("Enter a name: ")
count += 1
I'm fairly sure this code doesn't do what you intend. What this code is doing is checking the first through tenth elements of listOfNames for a number which is less than 10, but since its an empty list there is no element with index 0, or any other index for that matter hence your list index out of range exceptions.
The following will work as you intend:
count = 0
while len(listOfNames) < 10: # Keep going until the list has 10 elements
nameList.append(raw_input("Enter a name: "))
count += 1
However I'd suggest using the following which does exactly the same thing but should be more efficient as well as being more aesthetically pleasing:
for _ in range(10):
listOfNames.append(raw_input("Enter a name:"))
Note the use of append instead of an index reference. This will add the new element on to the end of the list whereas using the index as you were trying to do will fail since to assign to and index there has to be an element present in the first place.

Categories

Resources