Python Error: Int object not subscriptable - python

All right, I'm a novice at python, and here's the snippet of code in question:
<!-- language: lang-py -->
List = [["W","w"],["A","A"],["a","a"]]
def ascii():
x = 0
y = 0
aValues = [[],[],[]]
for item in List:
for item in List[x]:
c = "0"
c = ord(List[x[y]])
y = y + 1
aValues[x].append(c)
x = x + 1
return aValues
aValues = ascii()
print (aValues)
And, when I try to execute this, I get this error message:
>>>
Traceback (most recent call last):
File "/Users/Hersh/Desktop/Python/ascii_conversion.py", line 16, in <module>
aValues = ascii()
File "/Users/Hersh/Desktop/Python/ascii_conversion.py", line 10, in ascii
c = ord(List[x[y]])
TypeError: 'int' object is not subscriptable
>>>
What exactly is the problem, and how can I fix it?

As indicated in the error message, the erroneous line is
c = ord(List[x[y]])
x is an integer (like 0). Instead, you want:
c = ord(List[x][y])
i.e. take the x-th element of List (which is itself a list), and take the y-th element of that.
However, your method of iteration is very unpythonic. You never use the item variables, but you should. For example, a shorter way of writing the line is:
c = ord(item)
By using map and list comprehensions, you can cut down your code to:
def ascii():
return [map(ord, l) for l in List]

I'm not sure of what exactly you intend to do with the function, it has several errors. Try this and tell me if this is what you wanted:
List = [["W", "w"], ["A", "A"], ["a", "a"]]
aValues = [[ord(e1), ord(e2)] for e1, e2 in List]
print(aValues)
EDIT 1 :
Alternatively, if each sublist contains more than two elements, this version is better and will work for the general case:
aValues = [map(ord, pair) for pair in List]
EDIT 2 :
According to the comments, you need to use a function. All right, then let's implement the solution as a function - first thing, the input for the function should be received as a parameter, not as a global variable (List) as you have currently in your code. Then, the result will be returned, and I'll take the opportunity to show yet another way to solve the problem at hand:
def ascii(lst):
return [[ord(element) for element in pair] for pair in lst]
Use it like this:
List = [["W", "w"], ["A", "A"], ["a", "a"]]
ascii(List)
> [[87, 119], [65, 65], [97, 97]]

Hmm. Unfortunately you have quite a lot of issues here. They mostly stem from your misunderstanding of loops in Python.
When you do for item in List, item is set to each element in the list in turn. So, you can't then do for item in List[x] on the next line - that makes no sense. item is the inner list already - so you want to do for inner_item in item (or, call your outer list variable something more sensible).
The next two lines make no sense either. There's no point setting c to "0" then immediately setting it to something else. And don't forget, as I said above, you already have the item in the inner loop, which we've called inner_item. So your code should read c = ord(inner_item).
Hope this helps.

The correct way to index into a 2-dimensional list is not:
c = ord(List[x[y]])
But instead:
c = ord(List[x][y])
Your error comes from the fact that x[y] is an invalid sub-expression, because x is an integer and [] is the subscript operator. You cannot subscript an integer.
However, you don't actually need to index into your list to accomplish the same thing:
def ascii():
x = 0 ## redundant
y = 0 ## redundant
aValues = [[],[],[]]
for item in List:
for item in List[x]: ## you are reusing 'item', change the name here to 'subItem'
c = "0" ## redundant
c = ord(List[x[y]]) ## redundant, replace with: c = ord(subItem)
y = y + 1 ## redundant
aValues[x].append(c)
x = x + 1 ## redundant

Change line 10 to
c = ord(item)

x is not actually an array. It's an integer that you're incrementing.
You need to figure out what it is that you're trying to do, and look up the appropriate syntax for it. It's not very clear what x[y] is supposed to be representing.

Related

Bad Function Python

I am new to Python and learning by myself.
This is my first post here, I appreciate any help that you can give me.
I have been trying to find the min value and the index on a list with a function.
This is the code that I wrote:
def findMin (L,startIndx):
m = L[startIndx]
index = startIndx
for i in range (startIndx,len(L)):
x = L[i]
if i < m:
i = index
m = x
else:
pass
return (m,index)
a,b = findMin([8,2,11,0,5])
print (a,b)
This is the error that I get:
**TypeError Traceback (most recent call last)
<ipython-input-33-9713029875a6> in <module>
----> 1 a,b = findMin([8,2,11,0,5])
2 print (a,b)
TypeError: findMin() missing 1 required positional argument: 'startIndx'**
I truly have no idea what is the problem with it, I appreciate any help,
The problem that you ran into is that you only passed one argument (L) and not the second one (startIndx) and you have some logic errors in your code as mentioned by other answers.
This is a much shorter way of writing your function using some built-in functions that isn't that error-prone.
Very compact form:
def findMin(L,startIndx=0):
m = min(L[startIndx:])
return (m, L.index(m))
Here is the more spaced out version of that function with some explenations.
#Notice that startIndx is a OPTIONAL ARGUMENT. This means if we don't pass anything to it, it will be defined to be 0
def findMin(L,startIndx=0):
#The searchspace is defined by SLICING the list using list[from:upto]
searchspace = L[startIndx:]
#Using the built-in min() function we find the smallest value in the list
m = min(searchspace)
#Then we use the built-in list.index(value) function to find the index of the smallest element
#Quick reminder: The first value in a list has the index 0
index = L.index(m)
#Finally we return the needed values
return (m, index)
This is how the function is called with startIndx:
test_list = [5,0,9,4,11]
test_index = 3
a,b = findMin(test_list, test_index)
print(a,b)
#--> 4, 3
When you call the function without the startIndx argument it searches through the entire list, because the optional argument startIndx is set to 0.
test_list = [5,0,9,4,11]
a,b = finMin(test_list)
print(a,b)
#--> 0, 2
So I can see a few errors in your algorithm.
First error:
findMin() missing 1 required positional argument: 'startIndx'
This error is due to the fact that findMin is a function that takes two arguments. First argument is the array you want to find the minimum of ([8,2,11,0,5] in your example). The second one is the startIndex. It is the index which you want to start at while searching for the min. You can add this index to your function call or add a default value in your funtion declaration.
Second error:
line 6: if i < m:
This is not what you want to do. Here you are comparing i (which is the current index of your for loop) and m which is the minimum value so far. You want to compare x and m like this:
if x < m
Third and last error:
i = index
This is wrong. You want to swap these two variables and assign i to index like this:
index = i
Here is the final correct code:
def findMin (L,startIndx):
m = L[startIndx]
index = startIndx
for i in range (startIndx+1,len(L)):
x = L[i]
if x < m:
index = i
m = x
else:
pass
return (m, index)
a,b = findMin([8,2,11,3,1], 0)
print (a,b)
Call with two parameters; findMin([8,2,11,0,5]) passes a single list. Perhaps findMin([8,2,11,0,5], 0).
Indentation appears to be incorrect, and this is critical in Python. All lines from "m =" to "return" must be indented one more level.
Variable naming could be improved; part of the confusion is likely from names like "m", "x", etc. What does m mean, vs. for example max_val?
Indexing seems confused; first you set index = startIndx then use for i. Delete the index = and use for index in range (startIndx + 1, len(L)) (you already have L[startIndx]).
What is the desired behavior and return value if startIndx is > len(L)?
Why comparing i to m?
Optimization: don't need the else: pass. It means "otherwise, do nothing" which does not need to be explicit.
findMin has two parameters, but you only pass it one argument. You have two choices:
Pass the argument that findMin requires.
a,b = findMin([8,2,11,0,5], 0)
Remove the startIndx parameter and use 0 instead:
def findMin (L):
index = 0
m = L[index]
for i in range (len(L)):
x = L[i]
if x < m:
index = i
m = x
else:
pass
return (m,index)
def findMin (L,startIndx): this function will expect 2 arguments L and startIndx. So you'll have to pass 2 arguments as well. But you are passing only 1 argument findMin([8,2,11,0,5]). [8,2,11,0,5] as a list is one argument passed to L, then missing one for startIndx which results in error.
startIndx seems unnecessary as well since all the elements needs to be traverse.
def findMin(L):
m = L[0]
index = 0
for i in range (1,len(L)):
if L[i]<m:
m=L[i]
index=i
return (m,index)
a,b = findMin([8,2,11,0,5])
print (a,b)

how to delete and append in a list python

This is my code
k = []
dot = input('length:')
a, b = input('Enter:')
for i in range(0,dot):
k.append('.')
for i in range(a, b+1):
k[i].append('x')
print k
when i try to run this the output will be like,
length:9
Enter:3, 4
Traceback (most recent call last):
File "light_switch.py", line 8, in <module>
k[i].append('x')
AttributeError: 'str' object has no attribute 'append'
i want to insert a 'x' in the the place of '.'. so how do i do it.
If you want to replace the '.' in the second range with 'x', just do:
for i in range(a, b+1):
k[i] = 'x'
The error is because when you index to k[i] you get the str you put there, only k is a list, but the values are str. str, being immutable, lacks an append method (and since you say you want to replace, not concatenate, you wouldn't want an append-like operation anyway). If you wanted append-like behavior to each '.', you'd change k[i].append('x') to k[i] += 'x' (which is logically constructing a new concatenated str and assigning it back, rather than mutating in place), or to add a whole bunch of xs to the end of the list, you'd just do k.append('x').
Note: If a < 0 or b+1 > dot, this will raise an IndexError; the former is unfixable, the latter could be handled in a kludgy way by simply making the first for loop run over range(max(dot, b+1)) instead of range(dot).
To replace the dot with x you can try this code:
k = []
dot = input('length:')
a, b = input('Enter:')
for i in range(0,dot):
k.append('.')
for i in range(a, b+1):
k[i] = 'x'
print k
You already have a '.' at the location you are trying to add x so you just need to assign x instead of '.'. Location you are trying to access using a[j].append('x') is not a list and you are trying yo append x to it. So it is giving error.

how to multiply each element in a string with python

I have done some writing like below
new_list = ["000","122","121","230"]
for item in new_list:
r = [np.matrix([[0.5,0.5],[0,1]]),
np.matrix([[0.5,0.25],[0,1]]),
np.matrix([[0.5,0.25],[0,1]]),
np.matrix([[0.5,0],[0,1]])]
(W0,W1,W2,W3) = r
for i in item:
i == 0
if item[i] == 0:
return W0
elif item[i] == 1:
return W1
elif item[i] == 2:
return W2
else:
return W3
i = i + 1
list_new = [np.matrix([1,0]) * new_list * np.matrix([0.5],[1])]
print(list_new)
I want to create a program for example when the input from the list is "122", it will multiply each element inside "122" as matrix W1*W2*W2.
The final result should be like
np.matrix([1,0]) * new_list2 * np.matrix([0.5],[1])
The
new_list2
here should be all multiplication result from the new_list. Meaning
new_list2 = [W0*W0*W0,W1*W2*W2,...]
I run this code and keep getting a syntax error saying
"return" outside function
I want to ask did I missed something here or there is other function/way to make it done using python. I am using Python 3.5
Thank you for the answer.
As the error message says, you are using "return" outside a function, which just doesn't make sense since "return" means "exit the function now and pass this value (or None if you don't specify a value) to the caller". If you're not inside function there is no caller to returns to...
Something like this?
import numpy as np
from functools import reduce
new_list = ["000", "122", "121", "230"]
matrices = [
np.matrix([[0.5,0.50],[0,1]]),
np.matrix([[0.5,0.25],[0,1]]),
np.matrix([[0.5,0.25],[0,1]]),
np.matrix([[0.5,0.00],[0,1]])
]
def multiply(s):
mt_seq = (matrices[i] for i in map(int, item))
return reduce(np.multiply, mt_seq) # or reversed(mt_seq)
for item in new_list:
print(multiply(item))
You can just convert each digit in the string with int(digit), e.g. int('2'), and do it for every element of the string with map(int, '01234').
Then, it's just a matter of taking those matrices and multiplying them. (Sorry, I am not familiar with np.multiply and np.matrix and maybe you need to reverse the order of multplication)
reduce(fun, seq) applies fun to seq, like this: fun(fun(fun(seq[0], seq[1]), seq[2]), ...)

zip function to store multiple outputs for a return statement

def somefunction():
outputs = []
a = 0
while a < 100:
if a%2 == 0:
b = 2*a + 1
outputs.append(list(zip(a,b)))
a += 1
return outputs
The above code is not what i'm using exactly but produces the same error, why does the above code return:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
TypeError: zip argument #1 must support iteration
Is this a particularly efficient way of returning all the items within a function as one? If not, what is a better method?
It returns that error because of its exact error message; that is, the zip arguments must support iteration. You just have two numbers that you are trying to "store together". In that case, I'm assuming what you are looking for is the tuple data type. Either that or "put them together" with the list data type you already have. The zip is entirely unnecessary. I would suggest reading more about Python's built-in types.
Just get a list of tuples!! (or list if you prefer, but since you can't change tuples and you want to return all the outputs, tuples make more sense)
def somefunction():
outputs = []
a = 0
while a < 100:
if a%2 == 0:
b = 2*a + 1
tup = (a,b)
outputs.append(tup)
a += 1
return outputs
There is no need to use zip here, zip is for joining two lists together, you only have two integers so you can store them in a tuple and then append the tuple to outputs
when zip would work for this
Zip would work if you stored all as in a_list and all bs in b_list. Then you could do:
outputs.append(zip(a_list,b_list))
this is unnecessary because you can just append a and b together in a tuple to output just like my example. But that is how it would be done.
You can also use list comprehension in this case:
def f():
return [(x, 2*x + 1) for x in range(100) if x%2 == 0]

Why doesn't my function to swap variables swap variables?

First, I have this function:
def change_pos(a, b):
temp = a
a = b
b = temp
print 'Done'
And I call it in another function but it just print 'Done' and do nothing.
I write the code directly:
a = 1
b = 2
temp = a
a = b
b = temp
It works fine. Any suggestion here?
Second, this is my code
def check_exception(list):
for element in list:
# Take list of numbers
# \s*: Skip space or not (\t\n\r\f\v), \d: Number [0-9]
# ?: Non-capturing version of regular parentheses
first = re.compile("\s*(?:\[)(\d+)\s*(?:,)").findall(element)
last = re.compile("\s*(?:,)(\d+)\s*(?:\])").findall(element)
# Convert string to integer
first_int = map(int, first)
last_int = map(int, last)
# Check and code above works
i = 0
print first_int[i]
change_pos(first_int[i],first_int[i+1])
print first_int[i+1]
print len(first_int)
#print type(first_int[0])
# Sort
# Error: list index out of range at line 47 and more
i = 0
while i < len(first_int):
if first_int[i] > first_int[i+1]:
change_pos(first_int[i], first_int[i+1])
change_pos(last_int[i], last_int[i+1])
i += 1
# Check exception
j = 0
while j < len(last_int):
if last_int[j] < first_int[j+1]:
return false
break
else:
j += 1
continue
return true
And I see: IndexError: list index out of range at conditions after # Error
Thanks for any help. :)
Your change_pos function does nothing useful as it only swaps the variables inside the function, not the variables that was used to call the function. One method of accomplishing what you want is this:
def change_pos(a, b):
print 'DONE'
return b, a
and then using it becomes:
a, b = change_pos(a,b)
Or even without a function:
a, b = b, a
Secondly, I'm sure you can figure out why you're getting an index error on your own. But here's why anyways. Arrays are zero indexed and you are using the length of last_int in your while loop. Now imagine last_int has a length of 5. That means it has index values ranging from 0-4. In the last iteration of the loop you are attempting to access last_int[5] in your if statement (last_int[j+1]) which of course will give you an index error.
You may have been told that variables are locations in memory with data in it. This is not true for Python. Variables are just names that point to objects.
Hence, you can not in Python write a function such as the change_pos function you attempt to write, because the names you change will be the names used in the function, not the names used when calling.
Instead of this:
a = 1
b = 2
change_pos(a, b)
You will have to do this:
a = 1
b = 2
a, b = change_pos(a, b)
The function needs to look like this:
def change_pos(a, b):
return b, a
This give you a hint that there is an easier way, and indeed there is. You can do this:
a = 1
b = 2
a, b = b, a
So no need for a function at all.
Since you actually want to swap integers in a list, you can make a function like this:
def change_pos(lst, p):
lst[p], lst[p+1] = lst[p+1], lst[p]
But I don't think that adds significantly the the readability of the code.
Also your usage of this is prefixed with the comment #sort. But your code does not sort. It's a bit like a half-assed bubble sort, but I don't know why you would want to do that.
Numbers are immutable in python. His when you pass them to a function, the function works with copies of the variables. This can be tricky if you try this with mutable types like Lists. But python has this function covered with some neat syntax tricks.
a, b = b, a
This swaps two variables with no need for any additional functions.

Categories