You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An iterator is an object whose sole purpose is to guide iteration through some data structure.
87
-
In particular, `filter` makes sure that elements that do not satisfy the predicate are skipped.
88
-
It is a bit like a cursor that can move only to the right.
86
+
In particular, `filter` makes sure that elements that do not satisfy the predicate are skipped:
87
+
88
+
```python
89
+
for word infilter(str.isupper, ["THUNDERBOLTS", "and", "LIGHTNING"]):
90
+
print(word)
91
+
# prints:
92
+
# THUNDERBOLTS
93
+
# LIGHTNING
94
+
```
95
+
96
+
An iterator is a bit like a cursor that can move only to the right.
89
97
90
98
The main differences between containers (such as `list`s) and iterators are
91
99
92
-
- Containers can, depending on their contents, take up a lot of space in memory, but iterators are generally very small (regardless of how many elements they 'contain').
100
+
- Containers can, depending on their contents, take up a lot of space in memory, but iterators are typically very small regardless of how many elements they 'contain'.
93
101
- Containers can be iterated over multiple times, but iterators can be used only once.
94
102
95
103
To illustrate the latter difference:
@@ -109,10 +117,10 @@ Here, `sum` iterates over both `numbers` and `even_numbers` twice.
109
117
In the case of `numbers` everything is fine.
110
118
Even after looping through the whole of `numbers`, all its elements are still there, and so `sum` can ask to see them again without problem.
111
119
112
-
The situation with `even_numbers` is move involved.
120
+
The situation with `even_numbers` is less simple.
113
121
To use the _cursor_ analogy: after going through all of `even_number`'s 'elements' – actually elements of `numbers`– the cursor has moved all the way to the right.
114
-
It cannot move backwards, so if you wish to iterate over all even numbers then you need a new cursor.
115
-
We say the the `even_numbers` iterator is _exhausted_. When `sum` asks for its elements again, `even_numbers` comes up empty and so `sum` returns `0`.
122
+
It cannot move backwards, so if you wish to iterate over all even numbers again then you need a new cursor.
123
+
We say that the `even_numbers` iterator is _exhausted_. When `sum` asks for its elements again, `even_numbers` comes up empty and so `sum` returns `0`.
116
124
117
125
Had the highlighted solution not used `filter`, it might have looked like this:
This variant stores all the multiples in a `list` before summing them.
127
-
Such a list can potentially be very big.
128
-
For example, if `limit = 1_000_000_000` and `factors = [1]` then `multiples` will be a list 8 gigabytes large!
135
+
Such a list can become very big.
136
+
For example, if `limit = 1_000_000_000` and `factors = [1]` then `multiples` will take up 8 gigabytes of memory!
129
137
It is to avoid unnecessarily creating such large intermediate data structures that iterators are often used.
130
138
131
139
132
140
### A function expression: `lambda`
133
141
134
-
...
142
+
Typically, when using higher-order functions like `filter` and `map`, the function to pass as an argument does not yet exist and needs to be defined first.
143
+
144
+
The standard way of defining functions is through the `def` statement:
145
+
146
+
```python
147
+
defname(parameters):
148
+
statements
149
+
```
150
+
151
+
Downsides of this construct include
152
+
153
+
- the syntax can be a bit bulky
154
+
- it requires coming up with a fresh name
155
+
156
+
These qualities can be quite bothersome when you just need a simple function of no particular significance for single use only.
157
+
In situations like this you might like to use a **lambda expression** instead.
158
+
159
+
A lambda expression is a specific kind of expression that evaluates to a function.
160
+
It looks like this:
161
+
162
+
```python
163
+
lambdaparameters: expression # general form
164
+
lambdaa, b, x: a * x + b # specific example
165
+
```
166
+
167
+
This latter lambda expression evaluates to a function that takes three arguments (`a`, `b`, `x`) and returns the value `a * x + b`.
168
+
Except for not having a name, it is equivalent to the function defined by
169
+
170
+
```python
171
+
defsome_name(a, b, x):
172
+
return a * x + b
173
+
```
174
+
175
+
A lambda expression need not necessarily be passed as an argument.
176
+
It can also be applied to arguments immediately, or assigned to a variable:
177
+
178
+
```python
179
+
lambdaa, b, x: a * x + b
180
+
# ⟹ <function <lambda> at 0x000001F36A274CC0>
181
+
182
+
(lambdaa, b, x: a * x + b)(2, 3, 5)
183
+
# ⟹ 13
184
+
185
+
some_function =lambdaa, b, x: a * x + b
186
+
some_function(2, 3, 5)
187
+
# ⟹ 13
188
+
189
+
list(filter(
190
+
lambdas: len(s) <=3,
191
+
["aaaa", "b", "ccccc", "dd", "eee"]
192
+
))
193
+
# ⟹ ['b', 'dd', 'eee']
194
+
```
195
+
196
+
Only functions that can be defined using a single (`return`) statement can be written as a lambda expression.
197
+
If you need multiple statements, you have no choice but to use `def`.
198
+
199
+
The solution highlighted above assigns a lambda expression to a variable: `is_multiple`.
200
+
Some people consider this to be unidiomatic and feel one should always use `def` when a function is to have a name.
201
+
A lambda expression is used here anyway to demonstrate the feature, and also because the author prefers its compactness.
202
+
203
+
Had the highlighted solution not used `lambda`, it might have looked like this:
0 commit comments