Python. Generator expressions

Generator expressions. Differences between generator expressions and list generators

Before exploring this topic, it is recommended that you familiarize yourself with the following topic:


Contents


Search other resources:

1. Declaring and using a generator expression. General form

Generator expressions work in the same way as generator functions. In Python, a generator expression is a for loop construct that allows you to obtain a sequence of values that will be supplied to the calling code on demand (if necessary). In terms of syntax, generator expressions are similar to list generators, with only one difference when they are declared. A generator expression is declared in parentheses ( ), as opposed to a list generator, which is declared in square brackets [ ].

The general form of declaring and using a generator expression is as follows

IterObj = ( expression for variable in sequence [if condition] )

here

  • IterObj – an iterated object that supports the iteration protocol. Such an object contains a list of values that will be retrieved in the calling code on demand using the next() method;
  • expression – an expression that forms a sequence of new values;
  • variable – a counter variable that alternately takes values from sequence;
  • condition – conditional expression. This is the case when a sequence of values is formed according to some condition.

In addition to syntactic differences, generator expressions differ from list generators also in the way they are sequenced in the generated values (see next section).

 

2. Differences between list generators and generator expressions

The following differences exist between generator expressions and list generators:

  • the list generator is formed in square brackets [ ]. In turn, the generator expression is enclosed in parentheses ( );
  • the list generator creates a list of results in memory that can be retrieved or dumped many times. A generator expression creates a generator object that supplies one element at a time from a sequence. When accessing the generator object for the next element, each element is retrieved from the set and is no longer placed in this set. Retrieving an element from a generator object can be done automatically in a for loop or by calling the next() method.

Compared to list generators, using generator expressions has the following advantages:

  • generator expressions optimize memory usage by eliminating the need to store the entire list of results;
  • the efficiency of generator expressions increases with the volume of results to be returned.

 

3. An example demonstrating the difference between a generator expression and a list generator

The following example demonstrates the difference between list generators and generator expressions.

# Generator expressions and list generators. Comparison

# 1. Set the number of numbers to be generated
n = 8

# 2. Using a generator expression, parentheses are used here.
# 2.1. Get an iterable object
IterObj = ( i+1 for i in range(n) )
print("IterObj = ", IterObj)

# 2.2. Convert an iterable object to a list and output it
L = list(IterObj)
print("L = ", L) # L = [1, 2, 3, 4, 5, 6, 7, 8]

# 2.3. Re-get value from iterable object
L2 = list(IterObj)
print("L2 = ", L2) # L2 = [] - empty list, all values have already been retrieved

# 3. Using the list generator, square brackets are used here.
# 3.1. Form a list
ResultList = [ i+1 for i in range(n) ]
print("ResultList = ", ResultList)

# 3.2. Convert list to another list
L3 = list(ResultList) # L3 = [1, 2, 3, 4, 5, 6, 7, 8]
print("L3 = ", L3)

# 3.3. Re-convert the list to another list
L4 = list(ResultList)
print("L4 = ", L4)   # L4 = [1, 2, 3, 4, 5, 6, 7, 8]   - the list is not empty

Program result

IterObj = <generator object <genexpr> at 0x039714F0>
L = [1, 2, 3, 4, 5, 6, 7, 8]
L2 = []
ResultList = [1, 2, 3, 4, 5, 6, 7, 8]
L3 = [1, 2, 3, 4, 5, 6, 7, 8]
L4 = [1, 2, 3, 4, 5, 6, 7, 8]

As the result suggests, the generator expression generated an IterObj object, which was reused to produce an empty L2 list. Why empty list? Because all the values of the IterObj object have already been retrieved by the preliminary call to the list method, which resulted in the list L.

In turn, the list generator has formed a list with data in memory that can be reused without losing its integrity.

 

4. Examples of using generator expressions
4.1. Form a sequence and get a list from an iterable object

The simplest example of forming a sequence of integer values using a generator expression.

# Generator expressions

# 1. Set the number of numbers
n = int(input("n = "))

# 2. Using a generator expressions.
#   Get an iterable object
IterObj = (i+1 for i in range(n))
print("IterObj = ", IterObj)

# 3. Convert an iterable object to a list and display it
L = list(IterObj)
print("L = ", L)

Test example

n = 8
IterObj = <generator object <genexpr> at 0x03DF19B0>
L = [1, 2, 3, 4, 5, 6, 7, 8]

 

4.2. Generate a sequence of n random numbers and get a tuple

This object is then converted to a tuple using the tuple() method.

# Generator expressions

# 1. Include the random module
import random

# 2. Set the number of numbers to be generated
n = int(input("n = "))

# 3. Get an iterable object and output it
IterObj = ( random.randint(1, 100) for i in range(n) )
print("IterObj = ", IterObj)

# 4. Convert iterable object to a tuple
T = tuple(IterObj)

# 5. Output the result
print("T = ", T)

Test example

n = 10
IterObj =   <generator object <genexpr> at 0x03DD19B0>
T = (94, 12, 59, 16, 39, 96, 30, 37, 33, 60)

 

4.3. Using while loop and next() method to retrieve values from an iterated object

Retrieving values from an iterated object occurs through an implicit or explicit call to the next() method. If you use a for loop to retrieve values, then the next() method is called implicitly (automatically) and you do not need to implement an obvious call to this method. If the values are pulled in a while loop, then the next() method must be used.

The following example demonstrates using a while loop to retrieve values from an iterated object.

# Generator expressions and list generators.

# 1. Include the random module
import random

# 2. Set the number of numbers to be generated
n = int(input("n = "))

# 3. Get an iterated object with a sequence of numbers and output it
IterObj = ( random.randint(1, 100) for i in range(n) )
print("IterObj = ", IterObj)

# 4. Loop to retrieve values from an iterated object.
#    Combining a while statement and the next () method
i=0
L = [] # the resulting list of values
while i<n:
    # Get 1 element from an iterable object - next() method
    item = next(IterObj)

    # Add item to a list
    L = L + [item]

    # Increase iteration counter
    i = i+1

# 5. Display the result
print("L = ", L)

Test example

n = 8
IterObj = <generator object <genexpr> at 0x040819B0>
L = [66, 8, 6, 93, 1, 41, 77, 85]

 

4.4. Using for loop on an iterable object

In this example, retrieval of single values from the generated object is performed with a for loop. The next() method does not need to be called in this case. This method is called automatically.

# Generator expressions.

# 1. Set a string with a sequence of characters
s = str(input("s = "))

# 2. Get an iterated object containing the characters of the input string
IterObj = ( c for c in s )   # expression's generator
print("IterObj = ", IterObj)

# 3. Loop to retrieve values from an iterable object.
#   The for statement is used to form the list L.
L = []
for c in s: # Here the next () method is called implicitly (automatically)
    L = L + [c]

# 4. Display the result
print("L = ", L)

Test example

s = jklmn oprst
IterObj = <generator object <genexpr> at 0x03ED19B0>
L = ['j', 'k', 'l', 'm', 'n', ' ', 'o', 'p', 'r', 's', 't']

 

5. Formation of a sequence of numbers in a generator expression in accordance with the if condition. Example

The example uses the generator expression to form an iterated IterObj object containing a sequence of random even integers from the specified range.

# Generator expressions

# 1. Include the random module
import random

# 2. Input n
n = int(input("n = "))

# 3. Enter the range of possible values for integers [a; b]
a = int(input("a = "))
b = int(input("b = "))

# 4. Generate a list with a set of random numbers,
#   the list generator is used
numbers = [ random.randint(a, b) for i in range(n) ]

# 5. Based on listOfRandomNumbers, form an iterated object with paired numbers.
IterObj = ( i for i in numbers if i%2 == 0 ) # Generator expression with if statement

# 6. Display the result as lists
L1 = list(numbers)
L2 = list(IterObj)
print("L1 = ", L1)
print("L2 = ", L2)

Test example

n = 10
a = 1
b = 100
L1 = [68, 65, 44, 22, 74, 25, 3, 36, 13, 39]
L2 = [68, 44, 22, 74, 36]

 


Related topics