# Iterators and generators for real parameter higher order functions

## 1. A function is a variable

To define a function in Python Z is actually to define a variable whose type is function, and the function name is the variable name

Variable = lambda parameter list: return value

amount to:

def variable (parameter list)

Return return value

```a = [10, 20, 30]

def b():
print('Hello world')

c1 = a
print(a[-1])
print(c1[-1])

c2 = b
b()
c2()

c3 = b()

list1 = [100, a, b, b()]
print(list1)

print(list1[1][-1])
list1[2]()
```

## 2. Real parameter higher order function

### 2.1map :

Create a new sequence by specifying rules for the elements in one or more sequences

map (function, sequence) - converts the elements in the sequence into elements in a new sequence through the rules specified by the function

Function requirements: there is and only one parameter - pointing to each element in the following sequence

There is a return value - the element in the new sequence (there are parameters to represent the element in the original sequence and describe the relationship between the element in the new sequence and the element in the original sequence)

map (function, sequence 1, sequence 2) - converts the elements in two sequences into elements in a new sequence through the rules specified by the function

Function requirements: there are and only two parameters - each pointing to the elements in the next two sequences

There is a return value - the element in the new sequence (use parameters to represent the element in the original sequence and describe the relationship between the element in the new sequence and the element in the original sequence)

map (function, sequence 1, sequence 2, sequence 3)

Function requirements: there are and only three parameters - pointing to the elements in the following three sequences respectively

There is a return value

```# Exercise 1: get the single digits of all elements in num - > [4, 2, 7, 0, 1]
nums = [84, 72, 67, 90, 31]

# Method 1: List derivation
new_nums = [x % 10 for x in nums]
print(new_nums)

# Method 2: map
new_nums = list(map(lambda x: x % 10, nums))
print(new_nums)

# Exercise 2: create a sequence in which the elements are the sum of the elements at the corresponding positions of nums1 and nums2 - [32, 97, 97, 25]
nums1 = [23, 8, 90, 2]
nums2 = [9, 89, 7, 23]
new_nums = list(map(lambda x1, x2: x1 + x2, nums1, nums2))
print(new_nums)  # [32, 97, 97, 25]

# Exercise 3: convert to a new sequence by multiplying the elements in nums by 10 - > [230, 80, 900, 20]
# Requirement: use derivation and map
nums = [23, 8, 90, 2]
# Method 1:
new_nums = [x * 10 for x in nums]

# Method 2:
new_nums = list(map(lambda x: x * 10, nums))
print(new_nums)

# Exercise 4: given two lists of numbers, create a new sequence with the number of elements in the first list as ten digits and the number of elements in the second list as single digits
# [39, 89, 47, 21]
nums1 = [23, 8, 914, 2]
nums2 = [9, 89, 37, 231]
new_nums = list(map(lambda x1, x2: x1 % 10 * 10 + x2 % 10, nums1, nums2))
print(new_nums)

new_nums = list(map(lambda x1, x2: int(f'{x1 % 10}{x2 % 10}'), nums1, nums2))
print(new_nums)

# Exercise 5: there are two lists: student name and age. Create a list to save multiple student information according to the
# [{name ':' Xiao Ming ',' age ': 18}, {name': 'Zhang San', 'age': 21}, {name ':' Li Si ',' age ': 22}, {name': 'Lao Wang', 'age': 19}]
names = ['Xiao Ming', 'Zhang San', 'Li Si', 'Lao Wang']
ages = [18, 21, 22, 19]

students = list(map(lambda name, age: {'name': name, 'age': age}, names, ages))
print(students)

def temp(name, age):
"""Temporary function"""
return {'name': name, 'age': age}

students = list(map(temp, names, ages))
print(students)
```

### 2.2reduce :

Merge the elements in the sequence into one data according to the specified rules

reduce (function, sequence, initial value)

Function requirements: there are and only two parameters - the first parameter points to the initial value and the second parameter points to the elements in the sequence

Return value - determines the merge method (depending on what operations are performed on the element and initial value to merge)

```from functools import reduce

# Exercise: sum all elements in num - > 118 = > 0 + 10 + 20 + 32 + 56
nums = [10, 20, 32, 56]
result = reduce(lambda init, item: init + item, nums, 0)
print(result)

# Exercise 2: find the product of all elements in nums - > 480 = > 1 * 2 * 3 * 8 * 10
nums = [2, 3, 8, 10]
result = reduce(lambda init, item: init * item, nums, 1)
print(result)

# Exercise 3: combine data in nums - > '23810' - > int ('23810 ') = >' '+ str (2) + str (3) + str (8) + str (10)
nums = [2, 3, 8, 10]
result = reduce(lambda init, item: init + str(item), nums, '')
print(result, int(result))

# Exercise 3: merge the elements in names - > 'Xiao Zhang, Li Lao'
# '+' small '+' Zhang '+' Li '+' old '
# '+' Xiao Ming '[0] +' Zhang San '[0] +' Li Si '[0] +' Lao Wang '[0]
names = ['Xiao Ming', 'Zhang San', 'Li Si', 'Lao Wang']
result = reduce(lambda init, item: init + item[0], names, '')
print(result)

# Exercise 4: sum all elements in nums according to the value - > 40.0
# 0 + float(10) + float('12') + float(12.5) + float('5.5')
nums = [10, '12', 12.5, '5.5']
result = reduce(lambda init, item: init + float(item), nums, 0)
print(result)

# Exercise 5: sum all numeric data in nums - > 12 + 100 + 10.5 - > 122.5
# Two methods: using derivation and not using derivation
nums = [12, 'abc', '12.5', 100, 10.5]

# Method 1
# nums = [12, 100, 10.5]  -> 0 + 12 + 100 + 10.5
result = reduce(lambda init, item: init + item, [x for x in nums if type(x) in (int, float)], 0)
print(result)

# Method 2
# [12, 'abc', '12.5', 100, 10.5]  -> 0 + 12 + 0 + 0 + 100 + 10.5
result = reduce(lambda init, item: init + (item if type(item) in (int, float) else 0), nums, 0)
print(result)

# Exercise 6: know a list of students
students = [
{'name': 'Xiao Ming', 'age': 18, 'math': 90, 'chinese': 85, 'English': 60},
{'name': 'stu1', 'age': 22, 'math': 83, 'chinese': 80, 'English': 30},
{'name': 'stu2', 'age': 30, 'math': 67, 'chinese': 93, 'English': 87},
{'name': 'stu3', 'age': 19, 'math': 55, 'chinese': 76, 'English': 69},
{'name': 'stu4', 'age': 17, 'math': 79, 'chinese': 80, 'English': 90}
]
# 1) Seek the average score of class Chinese score - reduce
total_chinese = reduce(lambda init, item: init + item['chinese'], students, 0)
print('Average score of Chinese:', total_chinese / len(students))

# 2) Sort the list from large to small according to the average score of students - sorted, sort
# students.sort(key=lambda stu: stu['math'] + stu['chinese'] + stu['English'], reverse=True)
# print(students)

new_students = sorted(students, key=lambda stu: stu['math'] + stu['chinese'] + stu['English'], reverse=True)
print(new_students)

# 3) Associate the data in address to each student in turn - map
address = ['Chongqing', 'Chengdu', 'Beijing', 'Kunming', 'Shenzhen']

return stu

new_students = list(map(temp, students, address))
print(new_students)

```

## 3. Iterator

### 3.1 what is an iterator

Iterators are container data types - they can be traversed, converted to lists, tuples, and so on

The print iterator cannot view elements: cannot count the number of elements in the iterator:

If you want to get the element of the iterator, you must take the element out of the iterator, and once the element is taken out, the element does not exist in the iterator and cannot be added again.

### 3.2 how to create iterators

Method 1: use iter to convert other sequences into iterators (any sequence can be converted into iterators)

Method 2: create a generator

```iter1 = iter('hello')
iter2 = iter([10, 20, 30])
iter3 = iter({'name': 'Zhang San', 'age': 18})
iter4 = iter({100, 200, 300})
```

Iterator print cannot view element

```print(iter1)        # <str_iterator object at 0x1074358e0>
print(iter2)        # <list_iterator object at 0x1070138b0>
```

The iterator cannot count the number of elements

```# print(len(iter1))       # TypeError: object of type 'str_iterator' has no len()
```

### 3.3 getting elements of iterators

No matter how the elements in the iterator are obtained, the obtained elements will disappear from the iterator

1) Get a single element

Next (iterator) - gets the top element of the current iterator

2) Traversal

for variable in iterator:

Circulatory body

```iter1 = iter('hello')
print(next(iter1))      # h
print(next(iter1))      # e
print(next(iter1))      # l
print(next(iter1))      # l
print(next(iter1))      # o
# print(next(iter1))      # Error: StopIteration

iter2 = iter([10, 20, 30])
for x in iter2:
print(f'x:{x}')

# print(next(iter2))      # Error: StopIteration

iter3 = iter({'name': 'Zhang San', 'age': 18, 'gender': 'male'})
print(next(iter3))      # 'name'
for x in iter3:
print(f'x:{x}')

iter1 = iter('hello')
print(list(iter1))    # ['h', 'e', 'l', 'l', 'o']
# print(next(iter1))    # Error: StopIteration
```

## 4. Generator

### 4.1) what is a generator

A generator is a container (not storing multiple data, but an algorithm that generates multiple data) - it can be traversed or converted into lists, tuples, etc

The generator has all the characteristics of an iterator: elements cannot be seen in printing, the number of elements cannot be counted, and once the corresponding elements are obtained, they will disappear from the generator

### 4.2) how to create a generator

Call a function with the yield keyword to get a generator.

If an ordinary function is called, the function body will be executed when calling the function, and the return value of the function will be obtained:

If there is a yield in the called function body, the function body will not be executed and the return value of the function will not be obtained when calling the function. Instead, a generator object is obtained.

```def func1():
print('=======')
print('+++++++')
print('--------')
yield
# if False:
#     yield
return 100

result = func1()
print(result)       # <generator object func1 at 0x1031f6b30>
```

### 4.3) control the number and value of data generated by the generator

How many data can be generated by the generator and what data can be generated are determined by the function body of the function called when the generator is created, how many times yield will be encountered during execution, and the value after yield each time yield is encountered.

```def func1():
yield 100
yield 200
if 10 > 20:
yield 400
return 300
yield 300

gen1 = func1()
print(list(gen1))       # [100, 200]
# print(next(gen1))       # Error: StopIteration

# Exercise: write a generator to create three elements, 100, 200, and 300
def create_num():
# yield 100
# yield 200
# yield 300
for x in range(100, 301, 100):
yield x

gen2 = create_num()
print(next(gen2))
print(next(gen2))
print(next(gen2))
# print(next(gen2))     # Error: StopIteration

# print(next(create_num()))       # 100
# print(next(create_num()))       # 100
# print(next(create_num()))       # 100

```

### 4.4) principle of generating data by generator

```def func1():
yield 100
yield 200
if 10 > 20:
yield 400
return 300
yield 300

gen1 = func1()
print(list(gen1))       # [100, 200]
# print(next(gen1))       # Error: StopIteration

# Exercise: write a generator to create three elements, 100, 200, and 300
def create_num():
# yield 100
# yield 200
# yield 300
for x in range(100, 301, 100):
yield x

gen2 = create_num()
print(next(gen2))
print(next(gen2))
print(next(gen2))
# print(next(gen2))     # Error: StopIteration

# print(next(create_num()))       # 100
# print(next(create_num()))       # 100
# print(next(create_num()))       # 100

```

## 5. Use of modules

### 5.1) what is a module

A py file is a module, and the module name is the file name of the PY file

### 5.2) how to use the contents of another module in one module

Premise: only modules whose module name is an identifier and not a keyword can be used by other modules

Principle: import before use

### 5.3) module classification

System module - py file in Python environment

Custom module - a py file created by the programmer

### 5.4) how to import modules

1)import module name - imports the specified module. After importing, you can use all global variables in this module in the way of "module name."

2)from module name import variable 1, variable 2,... - import the specified module. After import, you can directly use the corresponding variable

3)from module name import * - imports the specified module. After importing, you can directly use all global variables in the module

4) Rename

import module name as new module name - rename the module

from module name import variable 1 as new variable 1, variable 2,... - rename the variable

```# Import method 1
# import test
# print(test.a)
# print(test.name)
# test.func1()

# import functools
# functools.reduce()

# Import method 2
# from test import a, func1
# print(a)
# func1()
# # print(name)           # NameError: name 'name' is not defined

# from functools import reduce
# reduce()

# Import method 3
# from test import *
# print(a)
# print(name)
# func1()

# Module rename
# import test as ts
# print(ts.a)
# print(ts.name)
# ts.func1()

# import test as ts
# test = 'study hard!'
# print(test[-1])
# ts.func1()

# from test import a, name as t_name
# name = 'Xiao Ming'
# print(name)
# print(t_name)
#
# print(a)

# import math
# print(math.factorial(10))

# from math import factorial
# print(factorial(10))

from math import factorial as fac
print(fac(10))
```

# Homework after class

```# 1. What has been saved in the points list is the coordinates of each point (the coordinates are represented by tuples, the first value is the x coordinate, and the second value is the y coordinate)
points = [(10, 20), (0, 100), (20, 30), (-10, 20), (30, -100)]
# The following problems are solved using real parameter higher-order functions
# 1) Gets the point with the largest y coordinate in the list
result = max(points, key=lambda item: item[-1])
print(result)

print('--------------------Split line------------------------')

# 2) Gets the point with the smallest x coordinate in the list
result1 = min(points, key=lambda item: item[0])
print(result1)

print('--------------------Split line------------------------')

# 3) Gets the point furthest from the origin in the list
result2 = max(points, key=lambda item: (item[0]) ** 2 + (item[-1] ** 2))
print(result2)

print('--------------------Split line------------------------')

# 4) The points are sorted from large to small according to the distance from the point to the x axis
points.sort(key=lambda item: item[1] if item[1] >= 0 else -item[1], reverse=True)
print(points)

print('--------------------Split line------------------------')

result3 = sorted(points, key=lambda item: item[1] if item[1] >= 0 else -item[1], reverse=True)
print(result3)

print('--------------------Split line------------------------')

# 2. Find the element with the largest absolute value in the list nums
nums = [15, 8, 36, -12, -58, 168, -72]
result4 = max(nums, key=lambda item: item if item >= 0 else -item)
print(result4)

print('--------------------Split line------------------------')

# 3. Two lists A and B have been. Create A dictionary with the map function. The element in A is key and the element in B is value
A = ['name', 'age', 'sex']
B = ['Zhang San', 18, 'female']
New dictionary: {'name': 'Zhang San', 'age': 18, 'sex': 'female'}
result5 = dict(map(lambda A1, B1: (A1, B1), A, B))
print(result5)

print('--------------------Split line------------------------')

# 4. It is known that the three lists represent the names, subjects and class numbers of five students respectively. Use map to spell the three lists into a dictionary representing the class information of each student
names = ['Xiao Ming', 'floret', 'Xiao Hong', 'Lao Wang']
nums = ['1906', '1807', '2001', '2004']
subjects = ['python', 'h5', 'java', 'python']
# Results: {'Xiaoming':'python 1906 ',' Xiaohua ':'h51807', 'Xiaohong':'java2001 ',' Lao Wang ':'python 2004'}
result6 = dict(map(lambda x, y, z:(x, (z + y)), names, nums, subjects))
print(result6)

print('--------------------Split line------------------------')

# 5. A list message has been created, and reduce is used to calculate the sum of all numbers in the list (using list derivation and not using list derivation)
message = ['Hello', 20, '30', 5, 6.89, 'hello']
# Result: 31.89
from functools import reduce

# Method 1:
result7 = reduce(lambda init, item: init + (item if type(item) in (int, float) else 0), message, 0)
print(result7)

print('--------------------Split line------------------------')

# Method 2:
result8 = reduce(lambda init, item: init + item, [x for x in message if type(x) in (int, float)], 0)
print(result8)

print('--------------------Split line------------------------')

# 6. It is known that the results of each student's subjects are saved in a dictionary list,
# 1) Calculate and add the average score of each student
studens = [
{'name': 'stu1', 'math': 97, 'English': 67, 'Chinese': 80},
{'name': 'stu2', 'math': 56, 'English': 84, 'Chinese': 74},
{'name': 'stu3', 'math': 92, 'English': 83, 'Chinese': 78},
{'name': 'stu4', 'math': 62, 'English': 90, 'Chinese': 88}
]
list1 = list(map(lambda student: (student['math'] + student['English'] + student['Chinese']) / 3, studens))
print(list1)

def temp(stu, score):
stu['average'] = score
return stu

result9 = list(map(temp, studens, list1))
print(result9)

print('--------------------Split line-----------------------')

# 2) Sort from high to low according to the average score
# Calculate average score
studens = [
{'name': 'stu1', 'math': 97, 'English': 67, 'Chinese': 80, 'avg':81},
{'name': 'stu2', 'math': 56, 'English': 84, 'Chinese': 74, 'avg':71},
{'name': 'stu3', 'math': 92, 'English': 83, 'Chinese': 78, 'avg':87},
{'name': 'stu4', 'math': 62, 'English': 90, 'Chinese': 88, 'avg':80}
]

# Sort from high to low according to the average score
result10 = sorted(studens, key=lambda item: item['avg'], reverse=True)
print(result10)

```

Keywords: Python Back-end

Added by james_kirk on Tue, 26 Oct 2021 17:32:54 +0300