List index out of range - python array error - python

File "C:\Users\Tom\Desktop\Tetris!\tetris.py", line 206, in typeSet
Globals.blockArray[i].x.append(7)
IndexError: list index out of range
I get the above error for the 4th line in typeSet
At initialization:
def main():
initialize()
def initialize():
Globals.running = True
addBlock()
class Globals:
running = True
blockArray = []
blockNum = 0
And then later on:
def addBlock():
Globals.blockArray.append(block())
class block:
def __init__(self):
self.id = Globals.blockNum
Globals.blockNum += 1
self.x = []
self.y = []
self.landed = False
self.blockType = 1#random.randint(1,6)
self.typeSet()
def typeSet(self):
i = self.id
if self.blockType == 1:
#square(i)
Globals.blockArray[i].x.append(7)
Globals.blockArray[i].y.append(0)
Globals.blockArray[i].x.append(7)
Globals.blockArray[i].y.append(1)
Globals.blockArray[i].x.append(8)
Globals.blockArray[i].y.append(0)
Globals.blockArray[i].x.append(8)
Globals.blockArray[i].y.append(1)
Edit: added more code and switched it so the id should start at 0. Error code hasn't changed

Not enough code. The error tells you the exact problem. Globals.blockArray does not have a member at position i. That's why you shouldn't work with global variables when you can avoid them, since it can be a hard time making sure your global variables have the expected values in them.

I'm not sure but maybe you want to do
Globals.blockArray.append(self)
in the init function, and also increase Globals.blockNum after the assignment to self.id.

Every time an instance of block is created, Globals.blockNum is incremented by 1 and self.id is set to the current value of Globals.blockNum.
Later (in typeSet) self.id is used to index into Globals.blockArray.
The error occurs when Globals.blockArray doesn't have at least self.id + 1 items in it.
If Globals.blockNum keeps increasing and its value is used (indirectly) to index into Globals.blockArray, this will likely cause the error (unless something causes Globals.blockArray to keep growing too.

While nothing immediate comes to mind looking at your code above, the first thing I would try would be to print the contents of Globals.blockArray, and Globals.blockArray[i].

Related

Updating local variable within function not working correctly [duplicate]

This question already has answers here:
Static variable in Python?
(6 answers)
Closed 1 year ago.
I'm trying to write a function that updates its local variable each time it is run but it is not working for some reason.
def max_equity(max_equity=0):
if current_equity() > max_equity:
max_equity = current_equity()
print(max_equity)
return max_equity
else:
print(max_equity)
return max_equity
and the function which it is calling
def current_equity():
for n in range(len(trade_ID_tracker)-1):
equity_container = 0
if (trade_ID_tracker[n,2]) == 0:
break
else:
if (trade_ID_tracker[n, 1].astype(int) == long):
equity_container += (df.loc[tbar_count,'Ask_Price'] - trade_ID_tracker[n, 2]) * trade_lots * pip_value * 1000
elif (trade_ID_tracker[n, 1].astype(int) == short):
equity_container += 0 - (df.loc[tbar_count,'Ask_Price'] - trade_ID_tracker[n, 2]) * trade_lots * pip_value * 10000
return (current_balance + equity_container)
but for some reason the max_equity() function prints current_equity() which I can only imagine means that either:
if current_equity() > max_equity:
is not doing it's job and is triggering falsely
or
max_equity = current_equity()
is not doing its job and max_equity starts at zero every time it is run.
In other words if I put max_equity() in a loop where current_equity() is
[1,2,3,4,5,4,3,2,1]
then max_equity() should return
[1,2,3,4,5,5,5,5,5]
But instead it returns
[1,2,3,4,5,4,3,2,1]
Here's a quick example test
ar = [1,2,3,4,5,4,3,2,1]
def stuff(max_equity=0):
if ar[n] > max_equity:
max_equity = ar[n]
print(max_equity)
else:
print(max_equity)
for n in range(len(ar)):
stuff()
Either way I'm kind of stumped.
Any advice?
local function variables are reset at each function call. This is essential for the behavior of functions as idempotent, and is a major factor in the success of the procedural programming approach: a function can be called form multiple contexts, and even in parallel, in concurrent threads, and it will yield the same result.
A big exception, and most often regarded as one of the bigger beginner traps of Python is that, as parameters are reset to the default values specified in the function definition for each call, if these values are mutable objects, each new call will see the same object, as it has been modified by previous calls.
This means it could be done on purpose by, instead of setting your default value as 0 you would set it as a list which first element was a 0. At each run, you could update that value, and this change would be visible in subsequent calls.
This approach would work, but it is not "nice" to depend on a side-effect of the language in this way. The official (and nice) way to keep state across multiple calls in Python is to use objects rather than functions.
Objects can have attributes tied to them, which are both visible and writable by its methods - which otherwise have their own local variables which are re-started at each call:
class MaxEquity:
def __init__(self):
self.value = 0
def update(max_equity=0):
current = current_equity()
if current > self.value:
self.value = current
return self.value
# the remainder of the code should simply create a single instance
# of that like ]
max_equity = MaxEquity()
# and eeach time yoiu want the max value, you should call its "update"
# method

Class method changing variable

I am kind of new to python and I am facing a lot of trouble because for some reason this value within my class method is updating by it self even though I didn't touch it. I can't even make it constant... Here is the relevant piece of code that does it.
the method that is called:
def swapping(self,pos,puzzle):
print('Old puzzle \n',puzzle)
# Getting Zero point index
zero = obj.null_pos(puzzle)
# Getting Index of varied position
var = puzzle[pos[0]][pos[1]]
#Swappping values
puzzle[zero[0,0],zero[0,1]] = var
puzzle[pos[0], pos[1]] = 0
new_puzzle = puzzle
print('New_puzzle \n',new_puzzle)
return new_puzzle
# The code has been snipped into relevant parts only
for i in range(len(child_node)):
# Check the hn of each node
print(child_node[i])
#where it occurs:
num_mispl = obj.misplaced_tiles(nod.swapping(child_node[i],new_puz))
# <-- new_puz #value changes and i didn't assign it to anything
temp_stor.append(num_mispl)

local variable 'highest' referenced before assignment

I've tried calling out through the function but still pops up this error message.
def mostExpensiveStock(self):
mostexpStock = 0
for r in self.getstockList():
if r.value(r.getamountPur, r.getpricePur) > mostexpStock:
mostexpStock = r.value(r.getamountPur, r.getpricePur)
highest = str(r) + "with a total value of RM" + str('%.2f'%mostexpStock)
return highest
Suppose that either:
self.getstockList() is empty; or
r.value(...) is negative for all members of self.getstocklist()
Then, your code will never assign any value to highest and thus your attempt to return highest will cause the exception you are seeing.
Suppose that you'd like to return None in this case. Then begin by providing a default value for highest
def mostExpensiveStock(self):
highest = None
mostexpStock = 0
...
I believe the problem is sometimes the if block isn't going to trigger. With the way your code is written if that were the happen you would still try to return the value highest, however without the if block triggering the value won't be created.
You could look going to an if else block.

Add to dictionary in if loop

I have an if loop in which I am trying to;
(1) Create a dataframe from a filepath.
(2) Format this dataframe
(3) Add that dataframe to a dictionary that is a property of an instance of a class.
Here is my code defining the class and the method:
class myClass:
def __init__(self, name, filepathlist):
self.name = name
self.filepathlist = filepathlist
def formatData(self):
i = 0
self.dataframeDict = {}
if i < (len(self.filepathlist) - 1):
DFRAW = pd.read_csv(self.filepathlist[i], header = 9) #Row 9 is the row that is not blank (all blank auto-skipped)
DFRAW['DateTime'], DFRAW['dummycol1'] = DFRAW[' ;W;W;W;W'].str.split(';', 1).str
DFRAW['Col1'], DFRAW['dummycol2'] = DFRAW['dummycol1'].str.split(';', 1).str
DFRAW['Col2'], DFRAW['dummycol3'] = DFRAW['dummycol2'].str.split(';', 1).str
DFRAW['Col3'], DFRAW['Col4'] = DFRAW['dummycol3'].str.split(';', 1).str
DFRAW = DFRAW.drop([' ;W;W;W;W', 'dummycol1', 'dummycol2', 'dummycol3'], axis = 1)
dictIndex = self.filepathlist[i][39:44]
self.dataframeDict.update({dictIndex: DFRAW})
i = i + 1
Then I create an instance of the class and run the method:
filepathlist = ['filepath1','filepath2']
myINST = myClass('Mydataname', filepathlist)
myINST.formatData()
I then expect myINST.dataframeDict to have two dataframes as per the 2 input filepaths and thus 2 iterations of the if loop. However only 1 is present.
What is the error in my code or my approach?
It is hard to tell whether this will completely solve your problem, because no dummy data is provided. You will, however, get one step closer to your solution if you replace if i < (len(self.filepathlist) - 1): with while i < (len(self.filepathlist) - 1):.
You are currently just checking if i=0 is smaller than len(self.filepathlist)-1. If so, then the if-block is executed once. What you are actually looking for is a loop that keeps on iterating, as long as i is smaller than len(self.filepathlist)-1. This is done with while-loops.
You need to change your condition to for i in range(len(self.filepathlist)):
(Also, remove the assignment of i as the for loop does it automatically. For the same reason, you should also remove the line which increments i).
If you want to use a while loop, change the if line to while i < len(self.filepathlist):.
Notice that there's no -1. This is because you're using < instead of <=. If you want to use -1, then you also need the <= as this will ensure the loop runs the correct number of times.

circular array class in python

I have a project to create a circular array class, and the language I will be using is python. I am new to classes in python, but after reading through some webpages and chapters in books I think I have an understanding of how they work. However I need help, so I figured I would come to the wonderful teachers here at SO :)
Our class must be able to implement several operations; insert at front, insert at back, insert at index, remove from front, remove from back, remove from index.
I have started coding but am running into some problems, and I am not 100% sure if my syntax is even right.
Here is what I have so far:
class circular:
def __init__(self):
self.store = []
self.capacity = len(self.store)
self.size = 0
self.startIndex = 0
self.endIndex = 0
def decrementIndex(self):
index = index - 1
if index < 0:
self.store = self.store + self.capacity
def incrementIndex(self):
index = index + 1
if index == self.capacity:
index = index - self.capacity
def addToBack(self, value):
self.store[self.endIndex] = value
self.endIndex = incrementIndex(self.endIndex)
self.size += 1
def addToFront(self, value):
if self.size == 0:
addToBack(self, value)
else:
self.startIndex = decrementIndex(self.startIndex)
self.store[self.startIndex] = value
self.size += 1
I stopped there to start testing some of the functions, primarily t he addTofront and addToback. Upon testing them in IDLE using c = circular() and c.addToBack(2) I get an index error...and I'm not sure why. That isn't the only problem, it's just where I have gotten stuck and need help moving forward.
I am posting here because I need help and want to learn, not because I am lazy and haven't tried researching my problem. Thanks already SO!
In __init__ you set
self.store = []
In addToBack you do
self.store[self.endIndex] = value
If this is the first operation on the circular array, and you pass 2 as the value, then that turns into
[][0] = 2
The problem should be obvious -- an empty list has no index of 0, it has no indexes at all.
You need to add the item to the list in a different way.
I'm not going to tell you exactly how as it's part of your homework to figure that out.

Categories