Python2.x:
for idx in range(0, int(100 / 0.5)):
print 0.5 * idx
outputs:
0.0
0.5
1.0
1.5
..
99.0
99.5
Numpy:
numpy.arange would also do the trick.
numpy.arange(0, 100, 0.5)
Answer from NPE on Stack OverflowPython2.x:
for idx in range(0, int(100 / 0.5)):
print 0.5 * idx
outputs:
0.0
0.5
1.0
1.5
..
99.0
99.5
Numpy:
numpy.arange would also do the trick.
numpy.arange(0, 100, 0.5)
If you have numpy, here are two ways to do it:
numpy.arange(0, 100, 0.5)
numpy.linspace(0, 100, 200, endpoint=False)
The range objects are special:
Python will compare range objects as Sequences. What that essentially means is that the comparison doesn't evaluate how they represent a given sequence but rather what they represent.
The fact that the start, stop and step parameters are completely different plays no difference here because they all represent an empty list when expanded:
For example, the first range object:
list(range(0)) # []
and the second range object:
list(range(2, 2, 2)) # []
Both represent an empty list and since two empty lists compare equal (True) so will the range objects that represent them.
As a result, you can have completely different looking range objects; if they represent the same sequence they will compare equal:
range(1, 5, 100) == range(1, 30, 100)
Both represent a list with a single element [1] so these two will also compare equal.
No, range objects are really special:
Do note, though, that even though the comparison doesn't evaluate how they represent a sequence the result of comparing can be achieved using solely the values of start, step along with the len of the range objects; this has very interesting implications with the speed of comparisons:
r0 = range(1, 1000000)
r1 = range(1, 1000000)
l0 = list(r0)
l1 = list(r1)
Ranges compares super fast:
%timeit r0 == r1
The slowest run took 28.82 times longer than the fastest. This could mean that an intermediate result is being cached
10000000 loops, best of 3: 160 ns per loop
on the other hand, the lists..
%timeit l0 == l1
10 loops, best of 3: 27.8 ms per loop
Yeah..
As @SuperBiasedMan noted, this only applies to the range objects in Python 3. Python 2 range() is a plain ol' function that returns a list while the 2.x xrange object doesn't have the comparing capabilies (and not only these..) that range objects have in Python 3.
Look at @ajcr's answer for quotes directly from the source code on Python 3 range objects. It's documented in there what the comparison between two different ranges actually entails: Simple quick operations. The range_equals function is utilized in the range_richcompare function for EQ and NE cases and assigned to the tp_richcompare slot for PyRange_Type types.
I believe the implementation of range_equals is pretty readable (because it is nice as simple) to add here:
/* r0 and r1 are pointers to rangeobjects */
/* Check if pointers point to same object, example:
>>> r1 = r2 = range(0, 10)
>>> r1 == r2
obviously returns True. */
if (r0 == r1)
return 1;
/* Compare the length of the ranges, if they are equal
the checks continue. If they are not, False is returned. */
cmp_result = PyObject_RichCompareBool(r0->length, r1->length, Py_EQ);
/* Return False or error to the caller
>>> range(0, 10) == range(0, 10, 2)
fails here */
if (cmp_result != 1)
return cmp_result;
/* See if the range has a lenght (non-empty). If the length is 0
then due to to previous check, the length of the other range is
equal to 0. They are equal. */
cmp_result = PyObject_Not(r0->length);
/* Return True or error to the caller.
>>> range(0) == range(2, 2, 2) # True
(True) gets caught here. Lengths are both zero. */
if (cmp_result != 0)
return cmp_result;
/* Compare the start values for the ranges, if they don't match
then we're not dealing with equal ranges. */
cmp_result = PyObject_RichCompareBool(r0->start, r1->start, Py_EQ);
/* Return False or error to the caller.
lens are equal, this checks their starting values
>>> range(0, 10) == range(10, 20) # False
Lengths are equal and non-zero, steps don't match.*/
if (cmp_result != 1)
return cmp_result;
/* Check if the length is equal to 1.
If start is the same and length is 1, they represent the same sequence:
>>> range(0, 10, 10) == range(0, 20, 20) # True */
one = PyLong_FromLong(1);
if (!one)
return -1;
cmp_result = PyObject_RichCompareBool(r0->length, one, Py_EQ);
Py_DECREF(one);
/* Return True or error to the caller. */
if (cmp_result != 0)
return cmp_result;
/* Finally, just compare their steps */
return PyObject_RichCompareBool(r0->step, r1->step, Py_EQ);
I've also scattered some of my own comments here; look at @ajcr's answer for the Python equivalent.
Direct quote from the docs (emphasis mine):
Testing range objects for equality with == and != compares them as sequences. That is, two range objects are considered equal if they represent the same sequence of values. (Note that two range objects that compare equal might have different start, stop and step attributes, for example range(0) == range(2, 1, 3) or range(0, 3, 2) == range(0, 4, 2).)
If you compare ranges with the "same" list, you'll get inequality, as stated in the docs as well:
Objects of different types, except different numeric types, never compare equal.
Example:
>>> type(range(1))
<class 'range'>
>>> type([0])
<class 'list'>
>>> [0] == range(1)
False
>>> [0] == list(range(1))
True
Note that this explicitly only applies to Python 3. In Python 2, where range just returns a list, range(1) == [0] evaluates as True.
In Python 3.x ,
range(0,3) returns a class of immutable iterable objects that lets you iterate over them, it does not produce lists, and they do not store all the elements in the range in memory, instead they produce the elements on the fly (as you are iterating over them) , whereas list(range(0,3)) produces a list (by iterating over all the elements and appending to the list internally) .
Example -
>>> range(0,3)
range(0, 3)
>>> list(range(0,3))
[0, 1, 2]
Ideally, if you only want to iterate over that range of values , range(0,3) would be faster than (list(range(0,3)) because the latter has the overhead of producing a list before you start iterating over it.
In Python 2.x , range(0,3) produces an list, instead we also had an xrange() function that has similar behavior of range() function from Python 3.x (xrange was renamed to range in Python 3.x)
For Python 3.5, From the documentation -
Range objects implement the collections.abc.Sequence ABC, and provide features such as containment tests, element index lookup, slicing and support for negative indices
So you can do things like -
>>> range(0,10)[5]
5
>>> range(0,10)[3:7]
range(3, 7)
>>> 5 in range(6,10)
False
>>> 7 in range(1,8)
True
And all of these are constant time operations , as can be seen from this test -
In [11]: %timeit a = xrange(0,1000000)[1000]
1000000 loops, best of 3: 342 ns per loop
In [12]: %timeit a = xrange(0,1000000)[10000]
1000000 loops, best of 3: 342 ns per loop
In [13]: %timeit a = xrange(0,1000000)[100000]
1000000 loops, best of 3: 342 ns per loop
In [14]: %timeit a = xrange(0,1000000)[999999]
1000000 loops, best of 3: 342 ns per loop
In [15]: %timeit a = xrange(0,10000000)[9999999]
1000000 loops, best of 3: 339 ns per loop
In [16]: %timeit a = xrange(0,1000000000000)[9999999999]
1000000 loops, best of 3: 341 ns per loop
It depends on what version of Python you are using.
In Python 2.x, range() returns a list, so they are equivalent.
In Python 3.x, range() returns an immutable sequence type, you need list(range(0,2)) to get a list.
A "for loop" in most, if not all, programming languages is a mechanism to run a piece of code more than once.
This code:
for i in range(5):
print i
can be thought of working like this:
i = 0
print i
i = 1
print i
i = 2
print i
i = 3
print i
i = 4
print i
So you see, what happens is not that i gets the value 0, 1, 2, 3, 4 at the same time, but rather sequentially.
I assume that when you say "call a, it gives only 5", you mean like this:
for i in range(5):
a=i+1
print a
this will print the last value that a was given. Every time the loop iterates, the statement a=i+1 will overwrite the last value a had with the new value.
Code basically runs sequentially, from top to bottom, and a for loop is a way to make the code go back and something again, with a different value for one of the variables.
I hope this answered your question.
When I'm teaching someone programming (just about any language) I introduce for loops with terminology similar to this code example:
for eachItem in someList:
doSomething(eachItem)
... which, conveniently enough, is syntactically valid Python code.
The Python range() function simply returns or generates a list of integers from some lower bound (zero, by default) up to (but not including) some upper bound, possibly in increments (steps) of some other number (one, by default).
So range(5) returns (or possibly generates) a sequence: 0, 1, 2, 3, 4 (up to but not including the upper bound).
A call to range(2,10) would return: 2, 3, 4, 5, 6, 7, 8, 9
A call to range(2,12,3) would return: 2, 5, 8, 11
Notice that I said, a couple times, that Python's range() function returns or generates a sequence. This is a relatively advanced distinction which usually won't be an issue for a novice. In older versions of Python range() built a list (allocated memory for it and populated with with values) and returned a reference to that list. This could be inefficient for large ranges which might consume quite a bit of memory and for some situations where you might want to iterate over some potentially large range of numbers but were likely to "break" out of the loop early (after finding some particular item in which you were interested, for example).
Python supports more efficient ways of implementing the same semantics (of doing the same thing) through a programming construct called a generator. Instead of allocating and populating the entire list and return it as a static data structure, Python can instantiate an object with the requisite information (upper and lower bounds and step/increment value) ... and return a reference to that.
The (code) object then keeps track of which number it returned most recently and computes the new values until it hits the upper bound (and which point it signals the end of the sequence to the caller using an exception called "StopIteration"). This technique (computing values dynamically rather than all at once, up-front) is referred to as "lazy evaluation."
Other constructs in the language (such as those underlying the for loop) can then work with that object (iterate through it) as though it were a list.
For most cases you don't have to know whether your version of Python is using the old implementation of range() or the newer one based on generators. You can just use it and be happy.
If you're working with ranges of millions of items, or creating thousands of different ranges of thousands each, then you might notice a performance penalty for using range() on an old version of Python. In such cases you could re-think your design and use while loops, or create objects which implement the "lazy evaluation" semantics of a generator, or use the xrange() version of range() if your version of Python includes it, or the range() function from a version of Python that uses the generators implicitly.
Concepts such as generators, and more general forms of lazy evaluation, permeate Python programming as you go beyond the basics. They are usually things you don't have to know for simple programming tasks but which become significant as you try to work with larger data sets or within tighter constraints (time/performance or memory bounds, for example).
[Update: for Python3 (the currently maintained versions of Python) the range() function always returns the dynamic, "lazy evaluation" iterator; the older versions of Python (2.x) which returned a statically allocated list of integers are now officially obsolete (after years of having been deprecated)].
Rather than using a decimal step directly, it's much safer to express this in terms of how many points you want. Otherwise, floating-point rounding error is likely to give you a wrong result.
Use the linspace function from the NumPy library (which isn't part of the standard library but is relatively easy to obtain). linspace takes a number of points to return, and also lets you specify whether or not to include the right endpoint:
>>> np.linspace(0,1,11)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
>>> np.linspace(0,1,10,endpoint=False)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
If you really want to use a floating-point step value, use numpy.arange:
>>> import numpy as np
>>> np.arange(0.0, 1.0, 0.1)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
Floating-point rounding error will cause problems, though. Here's a simple case where rounding error causes arange to produce a length-4 array when it should only produce 3 numbers:
>>> numpy.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])
range() can only do integers, not floating point.
Use a list comprehension instead to obtain a list of steps:
[x * 0.1 for x in range(0, 10)]
More generally, a generator comprehension minimizes memory allocations:
xs = (x * 0.1 for x in range(0, 10))
for x in xs:
print(x)
well, from the help:
>>> help(range)
range(...)
range([start,] stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
so the last increment is not stop, but the last step before stop.
- in countMe shouldn't the code go up till 18 ;
- why is the last number printed in countMe 15, and not 18 ;
- why is that in the second function oddsOut the function only founts till 7 for j and not 8 even though j is 8 ;
- why is the last number printed in oddsOut 14.
more generally speaking the answer to those questions is that in most of the languages, a range is defined as [start:stop[, i.e. the last value of the range is never included, and the indexes start always at 0. The mess being that in a few languages and when working on algorithmics, ranges start at 1 and are inclusive with the last value.
In the end, if you want to include the last value you can do:
def closed_range(start, stop, step=1):
return range(start, stop+1, step)
or in your example:
>>> def countMe(num):
>>> for i in range(0, num+1, 3):
>>> print (i)
>>>
>>> countMe(18)
0
3
6
9
12
15
18
>>>
The stop parameter in a range does not include that number for example
for i in range(0,5):
print i
would print 0-4 but not 5.
This is the results from using timeit on the two modules
bhargav@bhargav:~$ python -m timeit "for i in range(10, -1, -1):(i)"
1000000 loops, best of 3: 0.466 usec per loop
bhargav@bhargav:~$ python -m timeit "for i in reversed(range(0, 10 + 1)):(i)"
1000000 loops, best of 3: 0.531 usec per loop
As you can see, the second way is slower that is because it has an additional call to the function reversed.
The reversed() function in Python has a special case for when you pass it a range(). The only real difference between reversed(range(...)) and range(...) is that you can iterate over a range() more than once, but reversed() returns an iterator, so it can only be used once.
>>> iter(range(0, 10))
<range_iterator object at 0x7f735f5badb0>
>>> reversed(range(0, 10))
<range_iterator object at 0x7f735f5baf30>
You can see that in both cases, the iterator type is range_iterator. So, the performance of the loop itself will be identical in both cases.
Since the only overhead to reversed() is one extra function call, I always prefer reversed(range(10)) over range(9, -1, -1).
range takes three arguments, start, stop, and step.
range(20,-1,0):
says to go from 20 to -1 in steps of size 0.
That doesn't make sense, and so python threw an error.
In for loop:
range(20,-1,0)
# ^^ can't be zero , Obviously Jump can't be zero
To iterate in reverse order, you need to pass third argument is negative (read comments):
>>> range(20,-1, -1) #
[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> range(20,-1, -2)
[20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0]
To iterate in normal order you need to pass +ve number:
>>> range(0, 20, 1) # == range(0, 20) == range(20)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> range(0, 20, 2)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Read Python doc:
range(stop)
range(start, stop[, step])This is a versatile function to create lists containing arithmetic progressions. It is most often used in for loops. The arguments must be plain integers. If the step argument is omitted, it defaults to 1. If the start argument is omitted, it defaults to 0. The full form returns a list of plain integers
[start, start + step, start + 2 * step, ...]. If step is positive, the last element is the largeststart + i * stepless than stop; if step is negative, the last element is the smalleststart + i * stepgreater than stop.stepmust not be zero (or else ValueError is raised).
Hence you are getting ValueError: range() arg 3 must not be zero exception.
You can't use range for this. The third argument for range is a fixed step used to increment the value: it can't be used to multiply or divide the previous value.
Instead, use a while loop:
i = 1
while i < 100:
...
i *= 10 # or i /= 10 depending on what you want.
If you really want to use a list comprehension, you can do as suggested by Albin Paul:
li = [10**x for x in range(3) ] # [1, 10, 100]
li = [10**x for x in range(2, -1, -1) # [100, 10, 1]
You can simply use a generator expression, like
for i in (10 ** x for x in range(2, -1, -1)):
print(i)
# 100
# 10
# 1
Or, if you want your "power range" to be a reusable function, you can create your own, i.e.
def powrange(*args, base=10):
for i in range(*args):
yield base ** i
for i in powrange(2, -1, -1, base=10):
print(i)
# 100
# 10
# 1
range(a, b, s) is [a, a+s, a+2*s..., x] where x < b.
So range(0) -> range(0,0,1) generates an empty list. This means the inside of the for loop is skipped which returns True.
for i in range(n) means i shall iterate over the list [0,1,2....,n-1]. In your case range(0)=[] (an empty list) because there be no integer between 0 and 0. That's why this block of code is not getting executed:
for i in range(len(L) - 1): #empty list
if L[i] > L[i + 1]: #this line is not getting executed
return False
and this line is getting executed and it's returning True.
return True #this one is getting executed
You can use any of these:
# Create a range that does not contain 50
for i in [x for x in xrange(100) if x != 50]:
print i
# Create 2 ranges [0,49] and [51, 100] (Python 2)
for i in range(50) + range(51, 100):
print i
# Create a iterator and skip 50
xr = iter(xrange(100))
for i in xr:
print i
if i == 49:
next(xr)
# Simply continue in the loop if the number is 50
for i in range(100):
if i == 50:
continue
print i
In addition to the Python 2 approach here are the equivalents for Python 3:
# Create a range that does not contain 50
for i in [x for x in range(100) if x != 50]:
print(i)
# Create 2 ranges [0,49] and [51, 100]
from itertools import chain
concatenated = chain(range(50), range(51, 100))
for i in concatenated:
print(i)
# Create a iterator and skip 50
xr = iter(range(100))
for i in xr:
print(i)
if i == 49:
next(xr)
# Simply continue in the loop if the number is 50
for i in range(100):
if i == 50:
continue
print(i)
Ranges are lists in Python 2 and iterators in Python 3.