Files
practical-python/Notes/07_Advanced_Topics/02_Anonymous_function.md
David Beazley b5244b0e61 link experiment
2020-05-26 09:21:19 -05:00

161 lines
3.8 KiB
Markdown

# 7.2 Anonymous Functions and Lambda
### List Sorting Revisited
Lists can be sorted *in-place*. Using the `sort` method.
```python
s = [10,1,7,3]
s.sort() # s = [1,3,7,10]
```
You can sort in reverse order.
```python
s = [10,1,7,3]
s.sort(reverse=True) # s = [10,7,3,1]
```
It seems simple enough. However, how do we sort a list of dicts?
```python
[{'name': 'AA', 'price': 32.2, 'shares': 100},
{'name': 'IBM', 'price': 91.1, 'shares': 50},
{'name': 'CAT', 'price': 83.44, 'shares': 150},
{'name': 'MSFT', 'price': 51.23, 'shares': 200},
{'name': 'GE', 'price': 40.37, 'shares': 95},
{'name': 'MSFT', 'price': 65.1, 'shares': 50},
{'name': 'IBM', 'price': 70.44, 'shares': 100}]
```
By what criteria?
You can guide the sorting by using a *key function*. The *key function* is a function that receives the dictionary and returns the value in a specific key.
```python
def stock_name(s):
return s['name']
portfolio.sort(key=stock_name)
```
The value returned by the *key function* determines the sorting.
```python
# Check how the dictionaries are sorted by the `name` key
[
{'name': 'AA', 'price': 32.2, 'shares': 100},
{'name': 'CAT', 'price': 83.44, 'shares': 150},
{'name': 'GE', 'price': 40.37, 'shares': 95},
{'name': 'IBM', 'price': 91.1, 'shares': 50},
{'name': 'IBM', 'price': 70.44, 'shares': 100},
{'name': 'MSFT', 'price': 51.23, 'shares': 200},
{'name': 'MSFT', 'price': 65.1, 'shares': 50}
]
```
### Callback Functions
Callback functions are often short one-line functions that are only used for that one operation. For example of previous sorting example.
Programmers often ask for a short-cut, so is there a shorter way to specify custom processing for `sort()`?
### Lambda: Anonymous Functions
Use a lambda instead of creating the function.
In our previous sorting example.
```python
portfolio.sort(key=lambda s: s['name'])
```
This creates an *unnamed* function that evaluates a *single* expression.
The above code is much shorter than the initial code.
```python
def stock_name(s):
return s['name']
portfolio.sort(key=stock_name)
# vs lambda
portfolio.sort(key=lambda s: s['name'])
```
### Using lambda
* lambda is highly restricted.
* Only a single expression is allowed.
* No statements like `if`, `while`, etc.
* Most common use is with functions like `sort()`.
## Exercises
Read some stock portfolio data and convert it into a list:
```python
>>> import report
>>> portfolio = list(report.read_portfolio('Data/portfolio.csv'))
>>> for s in portfolio:
print(s)
Stock('AA', 100, 32.2)
Stock('IBM', 50, 91.1)
Stock('CAT', 150, 83.44)
Stock('MSFT', 200, 51.23)
Stock('GE', 95, 40.37)
Stock('MSFT', 50, 65.1)
Stock('IBM', 100, 70.44)
>>>
```
### (a) Sorting on a field
Try the following statements which sort the portfolio data
alphabetically by stock name.
```python
>>> def stock_name(s):
return s.name
>>> portfolio.sort(key=stock_name)
>>> for s in portfolio:
print(s)
... inspect the result ...
>>>
```
In this part, the `stock_name()` function extracts the name of a stock from
a single entry in the `portfolio` list. `sort()` uses the result of
this function to do the comparison.
### (b) Sorting on a field with lambda
Try sorting the portfolio according the number of shares using a
`lambda` expression:
```python
>>> portfolio.sort(key=lambda s: s.shares)
>>> for s in portfolio:
print(s)
... inspect the result ...
>>>
```
Try sorting the portfolio according to the price of each stock
```python
>>> portfolio.sort(key=lambda s: s.price)
>>> for s in portfolio:
print(s)
... inspect the result ...
>>>
```
Note: `lambda` is a useful shortcut because it allows you to
define a special processing function directly in the call to `sort()` as
opposed to having to define a separate function first (as in part a).
[Next](03_Returning_functions)