"Backlog" of a loop through a list in Python - python

I have a weird Python beginner's question,.. playing around in my virtual env in the interpreter (python 3.5):
I have a list with mixed types:
lissi = ["foo", "bar". "boo", "baz", 4, 7]
And then "accidentally" try to print out all elements in a for loop concatenated to a string:
for x in lissi:
print("Hallo " + x)
This, of course, is not possible bcs. we cannot conc. integers to a String - so the first elements are printed and then there is a TypeError.
Then I typed just "x" and enter to see if there is still data stored and yes it is: x is 4.
type(x) is int (tried that to figure out if 7 is also still there).
So my question is: What happens "under the hood" in Python in the for loop: Seems as if every successfully processed element is removed, but there is a backlog stored in x which is the first element the TypeError was thrown for? And is there a way to "clear" this data from memory in case of errors?
thx

The for loop is part of the scope it is declared in, so the following code will change the value of x:
x = 9
for x in xrange(3): # iterate 0, 1, 2
print(x)
print(x) # x == 2, x != 9
When the element was "baz", everything was okay and the print statement worked. Python then continued execution. The next step was x = 4. After that, print "Hallo" + x failed with an error.
While running the interpreter, errors are caught and printed, then execution continues. There is no cleanup after an error in the interpreter, so the last value of x is still there when you check the value. This is why you see 4.

It's not a backlog and nothing like "every successfully processed element is removed".
Basically on every iteration for loop assigns to variable x the value of next element of list lissi (doesn't have to be a list, can be any iterable).
Whenever the loop breaks, due to exception or break statement, variable x is left intact, so it contains the last value assigned by the for loop.
This is ok, since loops don't have any isolated scope in Python and actually makes it convenient to search iterable for interesting element, breaking the loop when it's found and not being forced to store it in another variable before leaving the loop.

I believe the problem is not with the for loop, but with the print() statement.
You cannot + a string with an integer, example:
This will not work:
print("Hallo " + 4)
nor will this:
print(4 + " Hallo")
if it is all integers it will work:
print(4 + 1)
the error which is shown from print("Hallo " + 4) is "builtins.TypeError: Can't convert 'int' object to str implicitly"
The solution is to do the conversion from integer to string explicitely:
for x in lissi:
print("Hallo " + str(x))
Now, for your question, I do not believe there is something as a "back log". The enumeration of for x in lissi is still valid, and x is still valid, just that while processing the first 4 enumerations (where x is a string) the print() statement will work, then it throws an error on the print() statement, but x is still a valid integer.

Related

Connecting last and first value of list

I have a list of numbers, say list= [0,1,0,1,0]. I have to check for each element i in list whether its equal to its previous and the element after it and if it is, change its value to the previous one. I presented this task as:
i-1=x
i+1=y
for i in list:
if x=y and i!=x
i=x
elif x!=y
i=i
But I need to connect the first and the last element in list, so that if i=list[0]: x=list[4] (and y=list[2]). My idea was to define another loop like this:
if i=list[0]
x=list[4]
But when i execute the program it writes that x=list[0] is "syntax error: invalid syntax". First, I am not quite sure why is this: I was thinking that I didn't define x (but I did!), or I maybe didn't define it in the right place (I am not sure where I should define it then). On the other hand, is this the way to connect last and first value of list?
Here is a code that does exactly what you asked.
test=[0,1,0,1,0] # don't use 'list' as variable name
for j in range(len(test)): # j=index of current
i = (j-1) % len(test) # i=index of previous
k = (j+1) % len(test) # k = index of next
if test[i] == test[k]: # equal to previous and next
test[j] = test[i] # change to previous
print(test)
Try this:
i-1=x
i+1=y
for i in list:
if x==y and i!=x :
i=x
elif x!=y
i=i
= means assignment whereas == means equality test. And the colon : in python defines the beginning of a scope (indented) so you need :' after anif` to define its scope block.

in 'for loops and range', although same range, two result differs. wanna know why

I'm currently learning python, and I found my self encountered some issue.
a={}
for i in range(0,10):
for j in str(i):
a[i]='%sth number'%(j)
b={}
for i in range(0,10):
for j in range(0,10):
b[i]='%sth number'%(j)
print(a)
print(b)
anyone could tell why does this two are different?
str(i) merely casts the integer i to a string. So doing for j in str(i): runs through every character in i as a string... which is only 1, in each case you've provided.
It would not run through all the numbers 0-9 as a string because you are casting each individual integer to a string as it is generated by the loop. If you put all the characters into a string first, then ran the second for loop through them, you might see the same results as the other loop.
In the first case you are going for each element only once inside and you are looking at the version of your number as a string.
In the second case for each number from 0 to 9 you are going again from 0 till 9 and the LAST case will overwrite all the precedence (thus you are getting always 9th)
In particularly replying your query, you can add an additional if cause:
if i == j: as below. In your second case I will explain a bit more:
i=1....then j=1; b[1] =1th
still i=1...then j=2; b[1] = 2th
still i=1...then j=3; b[1] = 3th
still...
....
....
still i=1...then LAST j=9; b[1] = 9th
now you are going into i=2:
i=2....then j=1; b[2] =1th
still i=2...then j=2; b[2] = 2th
still i=2...then j=3; b[2] = 3th
still...
....
....
still i=2...then LAST j=9; b[2] = 9th
And same will happen for all the i :-) Is it now clear?
Hope this clarify your query.
a={}
for i in range(0,10):
for j in str(i):
a[i]='%sth number'%(j)
b={}
for i in range(0,10):
for j in range(0,10):
if i == j:
b[i]='%sth number'%(j)
print(a)
print(b)
Why are these two different?
well str and range have completely different functionality.
str()
str(any_value) will simple convert any_value to a string "any_value"
eg: str(1) = "1", str(23.5) = "23.5"
range()
range(integer_value) will create a list from 0 to intger_value - 1
eg: range(5) = [0, 1, 2, 3, 4]
coming back to your question, in the first scenario your second loop won't go through a list of number, rather than an string representation of the number. Your inner loop is executed only 1 time on every outer loop iteration.
However in the second scenario you are actually traversing through a list of numbers generated by range(). Your inner loop is executed 9 times on every iteration of the outer loop.
Hope this helps :)
You can read more about str and range here.

'int' object has no attribute 'extend' - Python

I am trying to evaluate power series using python. series => e^x = 1+ x+ x^2/2! + x^3/3!...x^n/n!
I am getting this error ''int' object has no attribute 'extend'.
My code:
import math
print('give x')
x = float(input())
n =100
k = 0
list = (1)
while 0<x<1:
list.extend([math.pow(x,K+1))])
k = k+1
if x==n:
break
print(sum(list))
Please help!
There are multiple problems with your code.
Firstly, you are attempting to create a list with (1) - that just creates the integer object 1, the parentheses have no effect here. To create a list containing 1 you need [1]. And you shouldn't use the names of Python built-ins (like list) as variable names - not only is it confusing to other people who may read your code it makes the built-in inaccessible, which can lead to mysterious bugs.
K is not the same as k.
Your while 0<x<1: test does't make much sense; FWIW, the Taylor series for ex converges for all values of x.
Your if x==n: test should be if k==n:, although it'd be better to use a for loop with range (or maybe xrange in Python 2).
You don't need to save the terms in a list - just add them as you go.
You don't need math.pow - x**k calculates the same thing as math.pow(x, k), but even that's unnecessary here: you should just keep track of the previous term and multiply it by x on each loop.
You forgot the /n!. Once again, you don't really need to compute the factorial (or call the math.factorial function) since you can just divide the previous term by k.
Hopefully, that's given you enough clues to fix your code. I won't provide working code at this stage, since I suspect this is a homework problem. Note that the math module has an exp function which you can use to test the accuracy of your power series calculations.
A list literal is created with square brackets, []. You can use parentheses, (), for grouping or for creating a tuple. In the case of list = (1), they are being used for grouping, so this is the same as list = 1. (A tuple with one element is created with mytuple = (1,) or just mytuple = 1,.)
At this point, I'll mention that naming one of your variables list masks the built-in function list, so after you do that you can't access that function anymore without some effort. It's best to name your object something else, like lst.
A list's extend() method adds all the elements from the passed list onto the object you're accessing, so if mylist was [1, 2, 3], mylist.extend([4, 5]) would result in mylist becoming [1, 2, 3, 4, 5]. However, you only have one object to add, so it makes more sense to use append(), which adds the passed object to the given list.
x = float(input('Give x: ')) # the input function can be passed a prompt string
n = 100
k = 0
lst = [1] # changed name, created a list
while 0<x<1:
list.append(x**(k+1)) # you can just use the ** operator if you want
# also, k isn't K
k = k+1
if x==n: # x is never changed, so your loop either never runs
# or goes forever
break
print(sum(lst))
Note the while loop that will either never be entered or never finish. You'll have to take another look at your program's logic.

I need help wrapping my head around the return statement with Python and its role in this recursive statement

No this isn't homework but it is on our study guide for a test. I need to understand the role the return statement plays and the role recursion plays. I don't understand why the function doesn't break after x = 1.
def thisFunc(x):
print(x)
if x>1:
result=thisFunc(x-1)
print(result)
return x+1
Sorry, I understand how elementary this is but I could really use some help. Probably why I can't find an explanation anywhere...because it's so simple.
edit: Why does it print out what it does and what and why is the value of x at the end? sorry if I'm asking a lot I'm just frustrated
When you enter the function with a value n>1 it prints the current value, and then calls it's self with n-1. When the inner function returns it returns the value n - 1 + 1 which is just n. Hence, the function prints out the value n twice, once before the inner recursion and once after.
If n == 1, which is the base case, the function only prints 1 once and does not call it self again (and hence does not get result back to print). Instead it just returns, hence why 1 is only printed once.
Think of it like an onion.
calling thisFunc(n) will result in
n
# what ever the output (via print) of thisFunc(n-1) is
n
I don't understand why the function doesn't break after x = 1.
But it does:
>>> ================================ RESTART ================================
>>> x = 1
>>> def thisFunc(x):
print("Function called on x-value: ", x)
if x > 1:
result = thisFunc(x-1)
print(result)
return x+1
>>> thisFunc(x)
Function called on x-value: 1
2
>>>
edit: Why does it print out what it does and what and why is the value of x at the end?
Well, it prints it out because you're telling it to. Try following the value of x as you go through the function ("x is one, one is not bigger than 1; return 1+1. Ok. [new case] x is two, two is bigger than 1..." and so on).
return and recursion are part and parcel of programming; return statements designates the end of a function (even if you might have several lines more of code) and they also pass data back to whatever asked them for it. In your case you're asking "what happens when x is 1, given these rules?"; the returned data is your answer.
Recursion is simply the matter of letting the function call itself, should it (you) need to. You simply tell the program that "hey, as long as x is bigger than 1, call this function [that just so happens to be the same function initially called] on it and let it do its thing". To get a better understanding of your function I'd suggest that you add the line "Function called on x-value: " to the first print statement inside the function, or at least something that lets you identify which printed line is x and which is result.
For a more in-depth explanation on recursion, I recommend Recursion explained with the flood fill algorithm and zombies and cats

Forcing a variable to be an integer

errors = int(0)
for i in range(len(expectedData)):
if data[i] != expectedData[i]:
errors += int(binary_compare(data[i], expectedData[i]))
return errors
I have the above code which I am trying to use to calculate some integer (number of errors) for some data. I have casted everything I can see possible as an integer, yet the line "errors += ..." still appends the value, rather than adds it.
For example, if my answer should be 7, I might get 500002. (5 + 0 + 0 + .. + 2). I have never run into this before. The function binary_compare is returning an integer as well, but I'm completely in the dark as to why this isn't working.
python is not javascript
it's no way to get concatenated strings instead of math sum, when you do count += value starting with count = 0. if you try to add a string to integer, exception is raised:
>>> x = 0
>>> x += "1"
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
to compare values of which you don't know whether they are strings or integers, i'd use
str(data[i]).strip() == str(expectedData[i]).strip()
for noninteger-proof math sum, you might want to do something like this
try:
value = int(expectedData[i])
except:
value = 0
count += value
I think the error is outside of your code, but anyway, in Python, list operations are seldom done with loops, as this focuses on the implementation rather on the purpose. List comprehension, generators etc are preferred, and there are also many built-in and standard library functions for common tasks.
In your case, I would write the function as
return sum(binary_compare(x, y) for x, y in zip(data, expectedData) if x != y)
If you are using Python 2.x, itertools.izip should be used instead of zip.

Categories

Resources