Is defining a variable using a for loop possible in Python? - python

If I'd want to do for i in range(10): x+= 1 it obviously wouldn't work since x is undefined, I'd have to declare x e.g. x=0 before trying to write to it, but now I have two lines, one for declaring x=0 and one for actually writing the data I want to x (for i in range(10): x+= 1).
I was wondering, is there a way to do this in a single line? Or more specifically, declaring x as the result of a for loop?
Something along the lines of x = for i in range(10): x+= 1 ?
Would this even be possible or am I asking a nonsense question?

Not with a for statement.
However, you can use a similar construct, such as a list comprehension expression or a generator expression:
x = sum(i for i in range(10))
which is equivalent to just saying
x = sum(range(10))
Edit: as Dougal correctly notes, in your example you increment by 1, so the equivalent is
x = sum(1 for i in range(10))
which is in turn the same as x = len(range(10)) or just x = 10.

In most cases, i would imagine you would just want to use x as the loop variable:
for x in range(10): pass#or range(1,11)
An enumerate would also achieve a similar effect as what you are describing, assuming you want a different variable as the loop variable so as to do something else in the loop:
e.g.
for i,x in enumerate(range(x_start,x_end+1)):
#do something

Related

How to update a variable inside the while loop and see the results?

I want to use a for loop to define a range and I would like to use a while loop to check a condition for every value inside this for loop and give me the results for different values of c, but unfortunately, my algorithm doesn't work and I don't know what my mistake is.
j=0
jl=[]
c=np.linspace(0,20,num=20)
for a in range(0,len(c)):
while j<5:
j=c[a]+2
jl.append(j)
The result I am looking for is it puts different values of c inside the while loop and calculate j and check if it is bigger than 5 or not. if yes, it appends it to jl. Totally, I want to define a range with for loop with index and also check each value of this range inside while loop and get the results for j.
so expected results are j with values smaller than 5 (c[a]+2<5) and store the values of j in jl
There is one problem in your code:
j=0
"While loop" never runs because his condition is j>5. Correct that and tell us if it works.
Please double check if the following suggested solution covers all of your requirements. In any case I think List Comprehensions (e.g. compare section 5.1.3.) can help you.
c=np.linspace(0,20,num=20)
ls = [x+2 for x in c if((x+2)<5)]
print(ls)
Will result in the following output:
[2.0, 3.052631578947368, 4.105263157894736]
If you want to do more complex data manipulation, you can also do this with the help of functions, e.g. like:
def someManipulation(x):
return x+2
ls = [someManipulation(x) for x in c if(someManipulation(x)<5)]
Your algorithm doesn't work because
while j<5:
j=c[a]+2
is an infinite loop for j = 0, a = 0.
What you probably wanted to write was:
for x in c:
j = x + 2
if j < 5:
jl.append(j)
Still, the list comprehension version in the other answer does exactly the same, but better.

Difference In List - Python - Syntax Explanation [duplicate]

This question already has answers here:
Explanation of how nested list comprehension works?
(11 answers)
Closed 6 years ago.
Can someone please explain the meaning the syntax behind the following line of code:
temp3 = [x for x in temp1 if x not in s]
I understand it's for finding the differences between 2 lists, but what does the 'x' represent here? Each individual element in the list that is being compared? I understand that temp1 and s are lists. Also, does x for x have to have the same variable or could it be x for y?
[x for x in temp1 if x not in s]
It may help to re-order it slightly, so you can read the whole thing left to right. Let's move the first x to the end.
[for x in temp1 if x not in s yield x]
I've added a fake yield keyword so it reads naturally as English. If we then add some colons it becomes even clearer.
[for x in temp1: if x not in s: yield x]
Really, this is the order that things get evaluated in. The x variable comes from the for loop, that's why you can refer to it in the if and yield clauses. But the way list comprehensions are written is to put the value being yielding at the front. So you end up using a variable name that's not yet defined.
In fact, this final rewrite is exactly how you'd write an explicit generator function.
def func(temp1, s):
for x in temp1:
if x not in s:
yield x
If you call func(temp1, s) you get a generator equivalent to the list. You could turn it into that list with list(func(temp1, s)).
It iterates through each element in temp1 and checks to see if it is not in s before including it in temp3.
It is a shorter and more pythonic way of writing
temp3 = []
for item in temp1:
if item not in s:
temp3.append(item)
Where temp1 and s are the two lists you are comparing.
As for your second question, x for y will work, but probably not in the way you intend to, and certainly not in a very useful way. It will assign each item in temp1 to the variable name y, and then search for x in the scope outside of the list comprehension. Assuming x is defined previously (otherwise you will get NameError or something similar), the condition if x not in s will evaluate to the same thing for every item in temp1, which is why it’s not terribly useful. And if that condition is true, your resulting temp3 will be populated with xs; the y values are unused.
Do not take this as saying that using different variables in a list comprehension is never useful. In fact list comprehensions like [a if condition(x) else b for x in original_sequence] are often very useful. A list comprehension like [a for x in original_sequence if condition(x)] can also be useful for constructing a list containing exactly as many instances of a as the number of items in original_sequence that satisfy condition().
Try yourself:
arr = [1,2,3]
[x+5 for x in arr]
This should give you [6, 7, 8] that are the values on the [1,2,3] list plus 5. This syntax is know as list comprehension (or mapping). It applies the same instructions to all elements on a list. Would be the same as doing this:
for x in arr:
arr += 5
X is same variable and it is not y. It works same as below code
newList = []
for x in temp1:
if x not in s:
newList.append(x)
So x for x, here first is x which is inside append in code and x after for is same as for x in temp1.

Python nested forloop list comprehension

I'm trying to convert this working nested forloop into a single line list comprehension & i cannot seem to get it to work. The pseudo-code is as follows:
result = []
for x in something:
for y in x.address:
m = re.search("some pattern to match",y)
if m:
result += [m.group(1)]
Any pointers on how do i go about this ?
You'll need a generator expression..
matches = ( re.search(r'some pattern to match', y) for x in something
for y in x.address )
result = [ m.group(1) for m in matches if m ]
Nested loops are not really a problem for list comprehensions, as you can nest those there too:
lst = []
for y in z:
for x in y:
lst.append(f(x))
This translates into the following list comprehension:
[f(x) for y in z for x in y]
And you can easily continue that for multiple levels.
Conditions that decide on whether you want to add something to the list or not also work just fine:
lst = []
for x in y:
if t(x):
lst.append(f(x))
This translated into the following list comprehension with a filter:
[f(x) for x in y if t(x)]
Of course you can also combine that with multiple levels.
Now what is some kind of a problem though is when you want to execute something first, then filter on the result of that and append also something that depends on the result. The naive solution would be to move the function call inside and do it twice:
rexpr = re.compile('some pattern to match')
[rexpr.search(y).group(1) for x in something for y in x.address if rexpr.search(y)]
But this obviously runs the search twice which you generally want to avoid. At this point, you could use some hackish solutions which I generally wouldn’t recommend (as they harm readability). Since your result only depends on the result of the regular expression search, you could also solve this in two steps: First, you search on every element and map them to a match object, and then you filter on those matches and just return the valid ones:
[m.group(1) for m in (rexpr.search(y) for x in something for y in x.address) if m]
Note that I’m using generator expressions here: Those are essentially the same as list comprehensions, but don’t create the full result as a list but only yield on element at a time. So it’s more efficient if you only want to consume this one by one (which is the case here). After all, you’re only interested in the result from the list comprehension, so the comprehension will consume the generator expression.
I would do something like this:
# match function
def match(x):
m = re.search("some pattern to match",x)
if m:
return m.group(1)
else:
return None
#list comprehension
results = [match(y) for x in something for y in x.address if match(y)]

python in-line for loops

I'm wondering if there is a way in python to use a simplified, in-line for loop to do different things.
For example:
for x in range(5):
print(x)
to be written in a simpler form, such as
print (x) for x in range(5)
but this does not seem to be working.
I've been googling for finding the right syntax for a couple hours without success. The only alternative I found is, when the in-line for loop is used to access elements of a list:
print ([x for x in range(5)])
is working, but it is doing something else, than what I'm looking for.
Can someone point to the right syntax or let me know if there are any restrictions? (maybe in-line for loops work only about lists?)
Quick answer:
There is no such a thing as "in line for loops" in python
A trick that works:
in python 3.*:
[print(x) for x in range(5)]
Because print is a function
In python 2.* printis not a function but you could define myprint and use it like this:
>>> def myprint(x):
... print x
...
>>> _=[ myprint(x) for x in range(5)]
0
1
2
3
4
More in depth:
What you call "in-line for loops" or "shortforms" are actually list comprehensions and (quoting documentation)
provide a concise way to create lists
The first part of a list comprehension (before the forkeyword) must contain an expression used to create list values. If your expression contains a function that has the (side) effect of printing something it works... but it is exactly a side effect. What you are really doing is creating a list and then discarding it.
Note that you can't assign values (like q += (x * y)) in a list comprehension because assignments are not expressions.
You can join your items with new line character and print it.But this is not a proper way for just printing I recommend the your first code using a simple loop.
>>> print '\n'.join([str(x) for x in range(5)])
0
1
2
3
4
Or since map performs better at dealing with built-in functions rather than list comprehension you can use map(str, range(5))
The result would be your first code :
>>> for x in range(5):
... print(x)
...
0
1
2
3
4
You can also do it in one line :
>>> for x in range(5):print(x)
...
0
1
2
3
4

python iterate over the two lists while comparing items

i have two lists eg x = [1,2,3,4,4,5,6,7,7] y = [3,4,5,6,7,8,9,10], i want to iterate over the two lists while comparing items. For those that match, i would like to call some function and remove them from the lists, in this example i should end up with x= [1,2] and y = [8,9,10]. Sets will not work for this problem because of my type of data and the comparison operator.
for i in x:
for j in y:
if i ==j:
callsomefunction(i,j)
remove i, j from x and y respectively
Edit: After discovering the person asking the question simply didn't know about __hash__ I provided this information in a comment:
To use sets, implement __hash__. So if obj1 == obj2 when obj1.a == obj2.a and ob1.b == obj2.b, __hash__ should be return hash((self.a, self.b)) and your sets will work as expected.
That solved their problem, and they switched to using sets.
The rest of this answer is now obsolete, but it's still correct (but horribly inefficient) so I'll leave it here.
This code does what you want. At the end, newx and newy are the non-overlapping items of x and y specifically.
x = [1,2,3,4,4,5,6,7,7]
y = [3,4,5,6,7,8,9,10]
# you can leave out bad and just compare against
# x at the end if memory is more important than speed
newx, bad, newy = [], [], []
for i in x:
if i in y:
callsomefunction(i)
bad.append(i)
else:
newx.append(i)
for i in y:
if i not in bad:
newy.append(i)
print newx
print newy
However, I know without even seeing your code that this is the wrong way to do this. You can certainly do it with sets, but if you don't want to, that's up to you.
Ok, discard my post, I hadn't seen the point where you mentionned that sets wouldn't work.
Nevertheless, if you're OK with a little work, you might want to use classes so that operators do work as they are expected to.
I think the most "pythonistic" way of doing this is to use sets.
You could then do :
x = set([1,2,3,4,4,5,6,7,7])
y = set([3,4,5,6,7,8,9,10])
for item in x.intersection(y): #y.intersection(x) is fine too.
my_function(item) #You could use my_function(item, item) if that's what your function requires
x.remove(item)
y.remove(item)
I think that sets are also more efficient than lists for this kind of work when it comes down to performance (though this might not be your top priority).
On a sidenote, you could also use:
x,y = x.difference(y), y.difference(x)
This effectively removes items that are in x and y from x and y.
Try this:
for i in x:
if i in y:
callsomefunction(i)
x.remove(i)
y.remove(i)
EDIT: updated answer
how about this:
import itertools
x = [1,2,3,4,4,5,6,7,7]
y = [3,4,5,6,7,8,9,10]
output = map(somefunction, itertools.product(x,y))

Categories