Does range() return a list or a range object?

Why do we need to convert it to a list isn’t it already a list?
(if not then what is it?)

its not a list. Its a generator expression (not entirely, but close enough for now). Which hands you the values one by one rather then having all of numbers in memory (which a list does), so its more (memory) efficient.

10 Likes

Just to clarify, range() in Python 2 does return an object of type ‘list’,

>>> type (range(42))
<type 'list'>
>>> 

unlike Python 3 which returns a range object.

>>> type (range(42))
<class 'range'>
>>> 

The latter is a form of iterable that uses bounds, step and direction to know what the first value will be, and then the next, and the next, and so on until it has reached the other bound.

It is not an iterator, though, since it is not consumed in the process.

>>> a = range(10)
>>> for x in a: print (x, end='')
0123456789
>>> for x in a: print (x, end='')
0123456789

We see above that the range is unchanged. An iterator would not behave this way on the second or subsequent use. More on that later…

When we convert a range to a list (using the list constructor) the range is evaluated by the constructor and a list object is returned.

The nice thing about Python 3 range() is that it uses no more memory for a very large range than it would for a very small one.

7 Likes

Can you please elaborate “an iterator wouldn’t behave that way…”?

A range object is repeatedly iterable, which is not a property of iterators. The one thing that iterators have in common is that they are consumed on the first pass.

The big difference under the hood is that range has a defined __iter__() method, whereas iterators have a defined, next() method, which iterables do not. When the next method is invoked, it consumes the next value, thereby eventually consuming the entire object.

Take for example the zip() object.

>>> a = range(1, 27)
>>> b = map(lambda x: chr(x), range(97, 124))
>>> c = zip(a, b)
>>> d = {m: n for m, n in c}
>>> d
{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i', 10: 'j', 11: 'k', 12: 'l', 13: 'm', 14: 'n', 15: 'o', 16: 'p', 17: 'q', 18: 'r', 19: 's', 20: 't', 21: 'u', 22: 'v', 23: 'w', 24: 'x', 25: 'y', 26: 'z'}
>>> list(c)
[]
>>> 

Notice how the zip object, c is now empty?

6 Likes

thanks for giving me a heads up! i also researched some of it and now everything makes sense.

1 Like

Allow me to add here this excerpt from the python docs:

Blockquote
The advantage of the range type over a regular list or tuple is that a range object will always take the same (small) amount of memory, no matter the size of the range it represents (as it only stores the start , stop and step values, calculating individual items and subranges as needed).

3 Likes

I’m trying to learn python and few of your words is out of my scope will they come together by lessons you provide ?
like these ===>
iterator :man_with_probing_cane:
uses bounds :face_with_monocle:
It is not an iterator, though, since it is not consumed in the process. :pie:
range object. what ??? range object ? where this guy lives?
using the list constructor like class constructor in mighty js ?

turning back from js and trying to learn python and starting to feel …

>>> r = range(10)
>>> type (r)
<class 'range'>
>>> isinstance(r, range)
True
>>> len(r)
10
>>> hasattr(r, '__iter__')
True
>>> 

We see above a range object with a length of 10 that is iterable. The object itself cannot be represented in literal form,

>>> r
range(0, 10)
>>> 

so we must cast it to another more literal form such as a list , a tuple or a set.

>>> list(r)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> tuple(r)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> set(r)
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> 

if we wish to represent it in physical form. As a range object all it has are the three values it needs to generate a sequence… Start, Stop, Stride. This too is discussed in the narrative for this lesson (one would presume).

The term, bounds is used to describe the start and stop, or the endpoints of the sequence. We see them called, lower bound and upper bound in some literature. Think, boundary.

We learn about iterators in a later unit of the course. One thing they have in common is that they are consumed as they are accessed. This will be discussed at that time.

2 Likes

thank you , I see when comparing python to js , js is more like c++ in syntax when you have a tool and you can build everything you want out of it (for instance for loop I can have all of this functionality with just for loop and many more , python trying to make programming language more like typing English , at result evolving it, Is my opinion true ?

1 Like

Both are languages that sit atop of C++, though JS is more emulating the language than porting it. Python does generally make code easier to write and read without all the constraints of the parent language. It is to C++ what jQuery is to JS, in a way.

Bear in mind that both JS and Python are scripting languages, so both need an interpreter. Python having so close a tie to C++ (many of the built-ins are written in C++) offers better performance than JS since some of the code may be pre-compiled. Not so with JS, which does not pre-compile very much, if anything. It might retain some compiled code (cache) during a loop operation, but after the loop is done, the code is gone.

Python 3 has evolved to the point where some modules have been rewritten in Python, but of that I cannot say what with any certainty.

At any length, add this to your reading so you get more detailed and accurate information. Take what I write with a grain of salt.

3 Likes

I believe the confusion in this exercise,

Python 3
Creating and Modifying a List in Python
Range 1

is due to the variable names used(list1, list2). If I am correct from reading the responses above, in Python 2 while using the range() function it does return an object of type ‘list’, unlike Python 3 which returns a range object. With this being a Python 3 lesson I personally think that the variable names(in this section) should not include ‘list’. I was incredibly confused until reading the responses to this question. I tend to over analyze everything, so if I am incorrect please let me know.

If I want to print out <0,1,2,3,4,5,6,7,8,9>
How do you handle the last digit without a comma?
< for x in a: print (x, end = ', ')
always return a comma after the value. How to you remove the comma at the end of the 9. Thank you

>>> def hprint(a):
	for i in a[:-1]:
		print (i, end=', ')
	print (a[-1])

	
>>> hprint([1,2,3,4,5,6,7,8,9])
1, 2, 3, 4, 5, 6, 7, 8, 9
>>> 
2 Likes

Thanks, I just learn about it today. You’re awesome

1 Like

Great.
I just found the backspace key. Hence, a not so elegant way:
for i in a[:]:
print (i, end = ‘, ‘)
print(’\b’)