[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Generators, generator expressions, and loops


On 17/11/18 03:52, Steve Keller wrote:
> I have looked at generators, generator expressions, and iterators and
> I try to get more familiar with these.
> 1. How would I loop over all (with no upper bound) integers or all
> powers of two, for example?
> In C it would be
>     for (int i = 0; ; i++) { ... }  or  for (int i = 1; ; i *= 2) { ... }
> In Python, I could define a generator
>      def powers():
>          i = 1
> 	while True:
> 	    yield(i)
> 	    i *= 2
>      for i in powers():
>          ...

Is there a fundamental error here? Is the attempt to start from C (or 
whatever) and reproduce C-code in Python?

Whilst it can be a useful early-learning path to translate "commands" 
from one language to another, in order to commence actual usage quickly; 
one should not try to use such kindergarten techniques to discuss 
philosophy! First, learn the new language's idioms - a combination of 
language-vocabulary and its underlying culture.

In this case, the comparison is between the for-command of a for-loop 
(C), with Python's for-in structure. Python's idiom is to loop over the 
contents of something: the characters within a string of characters, the 
elements of a list, etc.

The C languages (and many others) have an idiom which controls the 
repetition of a loop without regard to the data being processed, ie for 
index = start-value, end-value, incremental-amount. This works 
regardless of what the code is looping 'over', if indeed, anything.

In Python, we don't look at the "index", this is provided (ie "batteries 
included"). Python looks at an instance of a collection object 
(previously "sequence members") which is also an iterator (see your 
previous questions). The mention of an iterable within a for-in 
statement causes the production of an appropriate element-value at each 
loop of the construct. Whereas with C one uses the index to choose which 
item of data to consider during this iteration of the loop, eg 
array[index]. In C the 'subject' of the loop is the index (or "offset"). 
In Python it is the collection, and iteratively, its elements.

This idiom removes a significant proportion of C (etc) programming 
errors caused by the necessity to use "pointers" or indices, eg the 
famous "out by one" error. Whereas in C it is necessary to use a pointer 
to loop over the two choices, in Python we can immediately use, eg
for gender in [ "male", "female" ]: with no pointer and direct access to 
the label-values, cf (define genders_array earlier, and then for index = 
1, 2; this_loops_gender = genders_array( index ); use this_loops_gender.

To directly answer the narrow coding-question posed: in Python one 
achieves "counting loops" using a while-construct, eg
	count = 0 #or start-value
	while ( count < maximum ):
		count += 1
The set-up, condition, and increment corresponding directly with the 
descriptions of "start-value, end-value, and increment-amount" in C 
(etc). In the case of "infinite loops: a common Python idiom is:
	while True:
with attendant start/increment code. In which case you enjoy all of the 
benefits of a generator (eg no need to generate (and store) all of the 
index values before looping commences) but without the abstraction in 
the example code - simplicity before complexity!

Python also offers a second-level answer in the Python Standard Library. 
The basic concepts of an iterator and/or the underlying technologies are 
made available in "itertools" - just as you will find with many other 
facilities within and around the language. There are a couple of 
specific edge-cases (a deliberate, never-ending loop) within that 
library. Enjoy!

Is it a valid approach to first solve a problem by 'thinking in C' and 
only then trying to translate that 'solution' into Python? This approach 
is where Star Wars' concept behind Yoda-speak comes from: some languages 
sequence the words in a sentence quite differently from the preferred 
subject-verb-object order of English:
	Jack hits the ball.
	Jack the ball hits.
	The ball hit (by) Jack.

IMHO Python is NOT a 'better version of C' - for any definition of 
"better", and regardless of anyone's enthusiastic preferences. There are 
situations where it would be 'better' to use one in preference to the 
other. Both ways! To write in Python, use Pythonic thinking, Python 
constructs (one author talks of "Python's beautiful heart"), and the 
idioms of Python; to realise its power!

Regards =dn