python parsers and generator expressions

Posted by tieded on Mon, 10 Jan 2022 03:52:43 +0100

Parsers and generator expressions

List parsing

The list parsing formula, list synthesis, is also called list derivation

#Generate a list, elements 0-9, and add the square value of 1 to each element to form a new list
x = []
for i in range(10):
    x.append((i+1)**2)
print(x
# List parsing
[(i+1)**2 for i in range(10)]

grammar

  • [return value for element in iteratable object if condition]

  • Brackets [] are used. The for loop is inside, and the if conditional statement is optional

  • Returns a new list

List parsing is a syntax sugar

  • The compiler will be optimized, which will not affect the efficiency due to abbreviation, but improve the efficiency due to optimization

  • Reduce programmer workload and reduce errors

  • Simplified code and enhanced readability

[expr for item in iterable if cond1 if cond2]
Equivalent to
ret = []
for item in iterable:
    if cond1:
if cond2:
ret.append(expr) 
#
[expr for i in iterable1 for j in iterable2 ]
Equivalent to
ret = []
for i in iterable1:
    for j in iterable2:
ret.append(expr)
# What are the following three outputs? Why?
[(i,j)  for i in range(7) if i>4 for j in range(20,25) if j>23]
[(i,j)  for i in range(7) for j in range(20,25) if i>4 if j>23]
[(i,j)  for i in range(7) for j in range(20,25) if i>4 and j>23]

Set analytic formula

grammar

  • {return value for element in iteratable object if condition}

  • When the brackets of the list parsing expression are replaced with braces {}, it becomes the set parsing expression

  • Returns a collection immediately

{(x, x+1) for x in range(10)}
{[x] for x in range(10)} # OK?

Dictionary parsing

grammar

  • {key:value for element in iteratable object if condition}

  • The brackets of the list parsing formula are replaced by braces {}, and the element is constructed in the form of key:value

  • Returns a dictionary immediately

{x:(x,x+1) for x in range(10)}
{x:[x,x+1] for x in range(10)}
{(x,):[x,x+1] for x in range(10)}
{[x]:[x,x+1] for x in range(10)} 
# {str(x):y for x in range(3) for y in range(4)} # How many elements are output?

Generator Expressions

grammar

  • (return value for element in iteratable object if condition)

  • Just replace the brackets of the list parsing formula with parentheses

  • Returns a generator object

And list parsing

  • Generator expressions are evaluated on demand (or lazy evaluation, deferred evaluation) and are evaluated only when needed

  • The list parse is an immediate return value

Generator object

  • Iteratable object

  • iterator

Generator Expressions List parsing
Delay calculation Calculate immediately
Returns an iteratable object iterator that can iterate Returns a list of iteratable objects, not iterators
You can only iterate once Repeatable iteration

Comparison between generator expression and list parsing

  • Calculation method

    • The generator expression delays the evaluation, and the list parsing expression evaluates immediately
  • Memory usage

    • Just from the return value itself, the generator expression saves memory and the list parsing returns a new list

    • The generator has no data and occupies very little memory. When used, returning one data at a time will only occupy the space of one data

    • List parsing to construct a new list requires immediate memory consumption for all elements

  • calculation speed

    • Looking at the calculation time alone, the generator expression takes a very short time and the list parsing takes a long time

    • But the generator itself does not return any value, only a generator object is returned

    • A new list is parsed and returned

summary

  • Python 2 introduces list parsing

  • Python2.4. Introduce generator expression

  • Python 3 introduced collection and dictionary parsing, and migrated to 2.7

Generally speaking, analytic expressions should be used more, which are short and efficient. If an analytic expression is very complex and difficult to understand, consider disassembling it into a for loop.

Generators and iterators are different objects, but they are both iteratable objects.

If you do not need to get the elements of all iteratable objects immediately, in Python 3, an iterator with lazy evaluation is recommended.

Built in function Function signature explain
sorted sorted(iterable[, key][, reverse]) Sort iteratable objects in ascending order by default
# Sorting must involve all participants in the container
print(sorted([1,2,3,4,5]))
print(sorted(range(10, 20), reverse=True))
print(sorted({'a':100, 'b':'abc'}))
print(sorted({'a':100, 'b':'abc'}.items()))
print(sorted({'a':'ABC', 'b':'abc'}.values(), key=str, reverse=True))
print(sorted({'a':2000, 'b':'201'}.values(), key=str))
print(sorted({'a':2000, 'b':'201'}.values(), key=int))

practice

  • Give three integers, use the if statement to judge the size, and output them in ascending order
def sorter(x,y,z):
    if x>y: #x,y
        if x>z: #(x,(z.y))
            if y>z:
                return x,y,z
            else:
                return z,z,y
    else: # y,x
        if y>z: #(y,(x,z))
            if x>z:
                return y,x,z
            else:
                return y,z,x
#or
def sorter(x,y,z):
    return sorted((x,y,z),key=int,reverse=False)
  • There is a list lst = [1,4,9,16,2,5,10,15], and a new list is generated. The new list element is required to be the sum of two adjacent items of lst
if __name__ == '__main__':
    lst = [1,4,9,16,2,5,10,15]  
    print([lst[i]+lst[i+1] for i in range(len(lst)-1)])
  • Randomly generate 100 product ID S in the following format

  • Sequential number, 6 digits, separator, dot, 10 random lowercase English characters

  • For example, 00000 5 xcbaaduixy

import random
import string

if __name__ == '__main__':
    alphabet=string.ascii_lowercase
    for i in range(100):
        print('{:0>6}.{}'.format(i,''.join(random.choices(alphabet,k=10))))