Ok, I'm in the process of learning Python, and had a quick question about for loops. I was wondering if you could use math operators in them, like JavaScript. For example, could I do:
for i = 0, i < 5, i++:
#code here
Now, I'm quite aware that Python doesn't support i++, and I think it doesn't support the commas either. So if I can do it that way, could you provide a sample.
Thanks
You would use a range loop:
for i in range(5):
#code here
If you want to increment in a loop you would use a while loop:
i = 0
while i < 5:
i += 1
To decrement you would use i -= 1.
Just as a loop is introduced by for, does not imply the same behaviour for different languages.
Python's for loop iterates over objects. Something like the C-for loop does not exist.
The C for loop (for ( <init> ; <cond> ; <update> ) <statement>, however, is actually identical to the C code:
<init>;
while ( <cond> ) {
<statement>
<update>
}
So, with the additional information that Python does have a while loop which behaves like the C-while loop, you should now be able to implement something like the C for loop in Python. I'll leave that as an exercise:-)
Note: as generating an evenly spaced sequence of integer values is a common case, Python provides the range() (Python 3) or xrange() (Python 2) function. This does create a RangeObject which (basically) yields the next value for a sequence given by start, stop and step arguments.
Quick answer
You may use:
for i in range(5):
# code here
or
i = 0
while i < 5:
i = i + 1 # or i += 1
Boring/pedantic answer
When I was learning Python I disliked the syntax; why should a simple for loop require a second keyword, range? The answer, I believe, is due to the fundamental role of the list in Python's prescriptive syntax. Repeated annoyances by range made me think about how the data were described (or not) before the loop, which in turn led me to think more Pythonically about the design of the data.
Let's say you want to populate a list with the first five perfect squares. You could:
squares = []
for i in range(5):
squares.append(i**2)
Alternatively, you could use comprehension:
initial_values = range(5) # we've declared the initial values
squares = [i**2 for i in initial_values]
Or more compactly:
squares = [i**2 for i in range(5)]
I routinely encounter problems where there's no Pythonic way to write the code, and I end up writing C-like Python (as in the Quick answer above). But just as often I find there's a more elegant and readable way to do things, and usually this indicates some imperfections in the antecedent data design.
Related
I was given code in Matlab made by someone else and asked to convert to python. However, I do not know MatLab.This is the code:
for i = 1:nWind
[input(a:b,:), t(a:b,1)] = EulerMethod(A(:,:,:,i),S(:,:,i),B(:,i),n,scale(:,i),tf,options);
fprintf("%d\n",i);
for j = 1:b
vwa = generate_wind([input(j,9);input(j,10)],A(:,:,:,i),S(:,:,i),B(:,i),n,scale(:,i));
wxa(j) = vwa(1);
wya(j) = vwa(2);
end
% Pick random indexes for filtered inputs
rand_index = randi(tf/0.01-1,1,filter_size);
inputf(c:d,:) = input(a+rand_index,:);
wxf(c:d,1) = wxa(1,a+rand_index);
wyf(c:d,1) = wya(1,a+rand_index);
wzf(c:d,1) = 0;
I am confused on what [input(a:b,:), t(a:b,1)] mean and if wxf, wzf, wyf are part of the MatLab library or if it's made. Also, EulerMethod and generate_wind are seprate classes. Can someone help me convert this code to python?
The only thing I really changed so far is changing the for loop from:
for i = 1:nWind
to
for i in range(1,nWind):
There's several things to unpack here.
First, MATLAB indexing is 1-based, while Python indexing is 0-based. So, your for i = 1:nWind from MATLAB should translate to for i in range(0,nWind) in Python (with the zero optional). For nWind = 5, MATLAB would produce 1,2,3,4,5 while Python range would produce 0,1,2,3,4.
Second, wxf, wyf, and wzf are local variables. MATLAB is unique in that you can assign into specific indices at the same time variables are declared. These lines are assigning the first rows of wxa and wya (since their first index is 1) into the first columns of wxf and wyf (since their second index is 1). MATLAB will also expand an array if you assign past its end.
Without seeing the rest of the code, I don't really know what c and d are doing. If c is initialized to 1 before the loop and there's something like c = d+1; later, then it would be that your variables wxf, wyf, and wzf are being initialized on the first iteration of the loop and expanded on later iterations. This is a common (if frowned upon) pattern in MATLAB. If this is the case, you'd replicate it in Python by initializing to an empty array before the loop and using the array's extend() method inside the loop (though I bet it's frowned upon in Python, as well). But really, we need you to edit your question to include a, b, c, and d if you want to be sure this is really the case.
Third, EulerMethod and generate_wind are functions, not classes. EulerMethod returns two outputs, which you'd probably replicate in Python by returning a tuple.
[input(a:b,:), t(a:b,1)] = EulerMethod(...); is assigning the two outputs of EulerMethod into specific ranges of input and t. Similar concepts as in points 1 and 2 apply here.
Those are the answers to what you expressed confusion about. Without sitting down and doing it myself, I don't have enough experience in Python to give more Python-specific recommendations.
So I'm new to Python and one concept that's taken some getting used to is the list comprehension. I've read that they can improve computation speed when used correctly and that they're something to know well if you're to learn Python the right way.
I'm writing a program that implements a particle aggregation algorithm that involves the accumulation of up to 10^6 particles to a growing cluster. I'm going back through my code to optimize performance anywhere possible, and I have the following function:
def step_all_walkers(walkers):
updated_positions = []
for walker in walkers:
decision = random.randint(1,4)
if decision == 1:
updated_walker = (min(walker[0]+1, N-1), walker[1])
elif decision == 2:
updated_walker = (max(walker[0]-1, 1), walker[1])
elif decision == 3:
updated_walker = (walker[0], min(walker[1] + 1, N-1))
elif decision == 4:
updated_walker = (walker[0], max(walker[1]-1, 1))
updated_positions.append(updated_walker)
return updated_positions
This function makes every particle (or walker, as I call them in the code) take a step of unit length in a random direction, and prevents the particles from walking off an N x N grid. I notice that I am creating and returning a new list updated_positions, and since this list and the input walker list are potentially very large, what I sort of know about list comprehensions tells me this might be a good time to use one. However, in some other posts on this question where there is only one if/else to be evaluated, people responded by saying just use a good ole fashion for loop.
I have a few questions then:
1) Can multiple if/elif statements be done in a list comprehension?
2) Does it make sense to write this for loop as a list comprehension? Are there any advantages to doing so?
My main purpose for asking this question is to build up more intuition for when a list comprehension is appropriate, and also to see if this function can be made more efficient with one.
I would turn that into a lookup dictionary to start with and then you might be able to consider a list comprehension
decisions = {1: lambda walker: (min(walker[0]+1, N-1), walker[1])}
return [decisions[random.randint(1,4)](walker) for walker in walkers]
A case where list comprehensions should not be used is when the logic in too complex.
For loops are simpler then since they allow:
Including comments to explain the code.
Use of control flow keywords like continue.
Debug of sections of the more easily using logging statements or asserts.
Allow others to easily see the complexity of the logic by scanning down the lines
However, as Sayse suggests, we can often simplify the logic with additional data structures and helper functions to allow list comprehension.
List comprehension with no if/else statements (need for logic bypassed)
def step_all_walkers(walkers, N):
def decision(walker):
" Helper function for making a decisions "
# Place decision choices into a data structure
options = [
lambda walker: (min(walker[0]+1, N-1), walker[1]),
lambda walker: (max(walker[0]-1, 1), walker[1]),
lambda walker: (walker[0], min(walker[1] + 1, N-1)),
lambda walker: (walker[0], max(walker[1]-1, 1))]
while True:
n = random.randint(0, 3) # use rather than (1, 4) to
# provide proper index into options
yield options[n](walker)
# Now, list comprehension is straight forward to follow
return [decision(walker) for walker in walkers]
This question already has answers here:
Is it possible to implement a Python for range loop without an iterator variable?
(15 answers)
Closed 7 months ago.
Suppose you want to write a program that asks the user for X numbers and store them in A, then for Y numbers and store them in B
BEFORE YOU VOTE FOR CLOSING : yes, this question has been asked here, here, here, here and possibly elsewhere, but I reply to each of the proposed solutions in this question explaining why they're not what I'm looking for, so please keep reading before voting for closing IF you decide it's a duplicate. This is a serious question, see last paragraph for a small selection of languages supporting the feature I'm trying to achieve here.
A = []
B = []
# First possibilty : using while loops
# you need to have a counter
i = 0
while (i < X):
A.append(input())
# and increment it yourself
i+=1
# you need to reset it
i = 0
while (i < Y):
B.append(input())
# and increment it again
i+=1
So basically you need to repeat a certain thing x times, then another Y times, but python has only while loops and for loops. The while loop is not to repeat a certain thing N times, but to repeat things while a certain condition is True, that's why you have to use a counter, initialize it, increment it, and test against it.
Second solution is to use for loops :
# No need to create a counter
for x in xrange(x):
A.append(input())
# No need to increment the counter
# no need to reset the counter
for x in xrange(Y):
B.append(input())
This is a lot better :), but there's still something slightly anoying : why would I still have to supply "x", when I don't need x ? In my code, I don't need to know in what loop iteration I am, i just need to repeat things N times, so why do I have to create a counter at all ? Isn't there a way to completely get rid of counters ? imagine you could write something like :
# No need to supply any variable !
repeat(x):
A.append(input())
repeat(Y):
B.append(input())
Wouldn't that be more elegant ? wouldn't that reflect more accurately your intention to possible readers of your code ? unfortunately, python isn't flexible enough to allow for creating new language constructs (more advanced languages allow this). So I still have to use either for or while to loop over things. With that restriction in mind, how do I get the most closer possible to the upper code ?
Here's what I tried
def repeat(limit):
if hasattr(repeat,"counter"):
repeat.counter += 1
return repeat.counter < limit
repeat.limit = limit
repeat.counters = 0
return limit > 0 and True
while repeat(x):
A.append(input())
while repeat(Y):
B.append(input())
This solution works for simple loops, but obviously not for nested loops.
My question is
Do you know any other possible implementation that would allow me to get the same interface as repeat ?
Rebbutal of suggested solutions
suggested solution 1.1 : use itertools.repeat
you'll have to place your code inside a function and call that function inside itertools.repeat, somehow. It's different from the above repeat implementation where you can use it over arbitrary indented blocks of code.
suggestion solution 1.2 : use itertools.repeat in a for loop
import itertools
for _ in itertools.repeat(None, N):
do_something()
you're still writing a for loop, and for loops need a variable (you're providing _), which completely misses the point, look again :
while repeat(5):
do_x()
do_y()
do_z()
Nothing is provided just for the sake of looping. This is what I would like to achieve.
suggested solution 2 : use itertools.count
1) you're half the way there. Yes, you get rid of manually incrementing the counter but you still need for a counter to be created manually. Example :
c = itertools.count(1,1) # You still need this line
while( c.next() < 7):
a = 1
b = 4
d = 59
print "haha"
# No need to increment anything, that's good.
# c.incr() or whatever that would be
You also need to reset the counter to 0, this I think could be hidden inside a function if you use the with statement on it, so that at every end of the with statement the counter gets reset.
suggested solution 3 : use a with statement
I have never used it, but from what I saw, it's used for sweeping the try/catch code inside another function. How can you use this to repeat things ? I'd be excited to learn how to use my first with statement :)
suggested solution 4 : use an iterator/generator, xrange, list comprehensions...
No, no, no...
If you write :
[X() for _ in xrange(4)]
you are :
1) creating a list for values you don't care about.
2) supplying a counter (_)
if you write :
for _ in xrange(4):
X()
see point 2) above
if you write :
def repeat(n):
i = 0
while i < n :
yield i < n
i+1
Then how are you supposed to use repeat ? like this ? :
for x in repeat(5):
X()
then see point 2) above. Also, this is basically xrange, so why not use xrange instead.
Any other cool ideas ?
Some people asked me what language do I come from, because they're not familiar with this repeat(N) syntax. My main programming language is python, but I'm sure I've seen this syntax in other languages. A visit of my bookmarks followed by online search shows that the following languages have this cool syntax :
Ruby
it's just called times instead of repeat.
#!/usr/bin/env ruby
3.times do
puts "This will be printed 3 times"
end
print "Enter a number: "
num = gets.chomp.to_i
num.times do
puts "Ruby is great!"
end
Netlogo
pd repeat 36 [ fd 1 rt 10 ]
;; the turtle draws a circle
AppleScript
[applescript]
repeat 3 times
--commands to repeat
end repeat
[/applescript]
Verilog
1 module repeat_example();
2 reg [3:0] opcode;
3 reg [15:0] data;
4 reg temp;
5
6 always # (opcode or data)
7 begin
8 if (opcode == 10) begin
9 // Perform rotate
10 repeat (8) begin
11 #1 temp = data[15];
12 data = data << 1;
13 data[0] = temp;
14 end
15 end
16 end
17 // Simple test code
18 initial begin
19 $display (" TEMP DATA");
20 $monitor (" %b %b ",temp, data);
21 #1 data = 18'hF0;
22 #1 opcode = 10;
23 #10 opcode = 0;
24 #1 $finish;
25 end
26
27 endmodule
Rebol
repeat count 50 [print rejoin ["This is loop #: " count]]
Forth
LABEL 10 0 DO something LOOP will repeat something 10 times, and you didn't have to supply a counter (Forth automatically stores it in a special variable I).
: TEST 10 0 DO CR ." Hello " LOOP ;
Groovy
you can either write 1.upTo(4){ code } or 4.times{ code } to execute code 4 times. Groovy is a blast when it comes to looping, it has like half a dozen ways to do it (upTo, times, step, java for, groovy for, foreach and while).
// Using int.upto(max).
0.upto(4, createResult)
assert '01234' == result
// Using int.times.
5.times(createResult)
assert '01234' == result
// Using int.step(to, increment).
0.step 5, 1, createResult
assert '01234' == result
WARNING: DO NOT DO THIS IN PRODUCTION!
I highly recommend you go with one of the many list comprehension solutions that have been offered, because those are infinitely less hacky. However, if you're adventurous and really, really, really want to do this, read on...
We can adapt your repeat solution slightly so that nesting works, by storing state that changes depending on where it's being called. How do we do that? By inspecting the stack, of course!
import inspect
state = {}
def repeat(limit):
s = tuple((frame, line) for frame, _, line, _, _, _ in inspect.stack()[1:])
counter = state.setdefault(s, 0)
if counter < limit:
state[s] += 1
return True
else:
del state[s]
return False
We set up a state dict to keep track of current counters for each unique place the repeat function is called, by keying off of a tuple of (stack_frame, line_number) tuples. This has the same caveat as your original repeat function in that break literally breaks everything, but for the most part seems to work. Example:
while repeat(2):
print("foo")
while repeat(3):
print("bar")
Output:
foo
bar
bar
bar
foo
bar
bar
bar
Surely you are over-thinking things. If I understand your (rather lengthy) question correctly you want to avoid repeating code. In this case you first port of call should be to write a function. This seems relatively simple: what you need is a function that takes an argument x (I have used n simply because it reminds me of integers) and returns a list containing that many input elements. Something like (untested):
def read_inputs(n):
ret_val = []
for i in range(n):
ret_val.append(input())
return retval
The remainder of your code is simply:
A = read_inputs(X)
B = read_inputs(Y)
Both of these bits of code do the same thing:
g = 1
g += 2
g += 17
print g
g = []
g.append(1)
g.append(2)
g.append(17)
print sum(g)
I was just wondering if one of these ways is "better" or more Python than the other.
My own testing with the following bit of code:
import time
n = 1000000
A = time.clock()
w = 0
for i in range(n):
w += i
print w, time.clock() - A
A = time.clock()
g = []
for i in range(n):
g.append( i )
print sum(g), time.clock() - A
seems to indicate that the first method is slightly faster, but I may be missing something.
Or I may be missing an entirely better way to perform this type of operation. Any input would be welcome.
It's not a matter of being Pythonic, it's a matter of what you want to achieve.
Do you want to save the values that constitute the sum so they can be referred to later? If so, use a list. If not, then why even bother with a list? It would just be a convoluted and less efficient way to do the same thing -- just add the values up. The direct addition method will obviously be faster because all you're doing is adding to a variable (very cheap), instead of mutating a list (which has a greater cost). Not to mention the evident memory advantage of using the direct addition approach, since you wouldn't be storing useless numbers.
Method A is
Add the integers
Method B is
Create a list of integers
Add the integers
If all you want to do is
Add the integers
I'd go with method A.
The only reason to have the second method is if you plan to use the list g elsewhere in the code. Otherwise, there isn't a reason to do it the second way. Making a list and then summing its values is a lot more costly then just incrementing a variable.
Moreover, if incrementing g is your goal, then why not do that? "Explicit is better than implicit" is a motto of Python. The first method explicitly increments g.
Also, the list may confuse people. When they see your code, they will think you need the list and plan to use it elsewhere. Not to mention that g is now a list. If g is supposed to be a number, having it be a list is not good and can lead to problems.
Finally, the first solution has less syntax (always a plus if it does the same job efficiently).
So, I'd go with method 1.
Absolutely the first, for many reason, first of all memory allocation (N integer instead just one) and performance: in real world application the GC overhead would pop out.
edit: disregard this, I can see now that it is not generally true, and is only true for specific values of x.
Ok, so I can see that making a list should be inefficient, but then why does fun2 run more quickly in this instance? Doesn't it essentially create a list and then sum over it?
import timeit
def fun1(x):
w = 0
for i in range(x):
w += i
return w
def fun2(x):
return sum([i for i in range(x)])
timer = timeit.Timer(stmt='fun1(10000)', setup='from __main__ import fun1')
print timer.timeit(number=10000)
timer = timeit.Timer(stmt='fun2(10000)', setup='from __main__ import fun2')
print timer.timeit(number=10000)
I've started learning Python a few days ago and I ran into a program while coding something.
Here's what I want to do using C++ code
number = SOME_NUMBER;
while(1) {
for(int i=number; i<sizeOfArray; i++) {
// do something
}
number = 0;
}
Basically, for the very first iteration of my for loop, I want to start i at number.
Then for every other time i go through the for loop, I want to start it at 0.
My kind of hacky idea that I can think of right now is to do something like:
number = SOME_NUMBER
for i in range(0, len(array)):
if i != number:
continue
// do something
while True:
for i in range(0, len(array)):
// do something
Is this the best way or is there a better way?
what is the problem with this?
starting_num = SOME_NUMBER
while True:
for i in xrange(starting_num, len(array)):
# do code
starting_num = 0
it does exactly what you want.
however, i think there are better ways to do things especially if the solution seems "hacky".
if you gave an idea of what you wanted to do, maybe there is a better way
I don't see why you couldn't just do the same thing you are in C:
number = SOME_NUMBER
while True:
for i in range(number, len(array)):
# do something
number = 0
BTW, depending on which version of Python you're using, xrange may be preferable over range. In Python 2.x, range will produce an actual list of all the numbers. xrange will produce an iterator, and consumes far less memory when the range is large.
In Python, stepping over a collection in the traditional sense is not ideal. The ability to loop - to iterate - over an object is controlled by the object, so you don't need to manually step through counters as you would in the for loop in C++.
As I understand it, what you are trying to do here is execute the same piece of code over each item in a list (there are no arrays in Python), a multiple number of times.
To do that:
def whatever_function(foo):
# some code here that works on each item on the list
# foo is an item of the list
while True:
map(whatever_function, some_list)