# 4.7. FuncProg First-class Functions¶

• Function can be assigned to variable

• Function can be stored in data structures such as hash tables, lists, ...

• Function can be returned

• Function can be user as a parameter

## 4.7.1. Assigning Functions¶

• Function can be assigned to variable

>>> def addition(a, b):
...     return a + b
>>>
>>>
>>>
3
>>>
7


## 4.7.2. Storing Functions¶

• Function can be stored in data structures such as hash tables, lists, ...

>>> def square(x):
...     return x ** 2
>>>
>>> def cube(x):
...     return x ** 3
>>>
>>>
>>> operations = (cube, square)

>>> def square(x):
...     return x ** 2
>>>
>>> def cube(x):
...     return x ** 3
>>>
>>>
>>> operations = {
...     'cube': cube,
...     'square': square,
...     'root': lambda x: x ** (1/2)
... }

>>> def increment(x):
...     return x + 1
>>>
>>> def decrement(x):
...     return x - 1
>>>
>>> def square(x):
...     return x ** 2
>>>
>>> def cube(x):
...     return x ** 3
>>>
>>>
>>> data = [1,2,3,4]
>>> operations = [increment, square, decrement, cube]
>>>
>>> for operation in operations:
...     data = list(map(operation, data))
>>>
>>> data
[27, 512, 3375, 13824]


## 4.7.3. Returning Functions¶

• Function can be returned

>>> def get_greeting(lang='English'):
...
...     def english(firstname, lastname):
...         print(f'Hello {firstname} {lastname}')
...
...     def polish(firstname, lastname):
...         print(f'Witaj {firstname} {lastname}')
...
...     match lang:
...         case 'English': return english
...         case 'Polish':  return polish
...         case _:         raise NotImplementedError
>>>
>>>
>>> greeting = get_greeting('English')
>>> greeting('Mark', 'Watney')
Hello Mark Watney
>>>
>>> greeting = get_greeting('Polish')
>>> greeting('Mark', 'Watney')
Witaj Mark Watney
>>>
>>> greeting = get_greeting('Spanish')
Traceback (most recent call last):
NotImplementedError


## 4.7.4. Parameter Functions¶

• Function can be user as a parameter

>>> from urllib.request import urlopen
>>>
>>>
>>> def fetch(url: str,
...           on_success = lambda response: ...,
...           on_error = lambda error: ...,
...           ) -> None:
...     try:
...     except Exception as error:
...         on_error(error)
...     else:
...         on_success(result)

>>> fetch(
...     url = 'https://python.astrotech.io',
...     on_success = lambda resp: print(resp),
...     on_error = lambda err: print(err),
... )

>>> def ok(response: str):
...     print(response)
>>>
>>> def err(error: Exception):
...     print(error)
>>>
>>>
>>> fetch(url='https://python.astrotech.io')
>>> fetch(url='https://python.astrotech.io', on_success=ok)
>>> fetch(url='https://python.astrotech.io', on_error=err)
>>> fetch(url='https://python.astrotech.io', on_success=ok, on_error=err)
>>> fetch(url='https://python.astrotech.io/not-existing', on_error=err)


## 4.7.5. Use Case - 0x01¶

>>> def map(func, data):
...     ...

>>> def filter(func, data):
...     ...

>>> def reduce(func, data):
...     ...


## 4.7.6. Use Case - 0x02¶

>>>
... import pandas as pd
...
...
... DATA = 'https://python.astrotech.io/_static/phones-pl.csv'
...
... result = (
...     pd
...     .set_index('datetime', drop=True)
...     .drop(columns=['id'])
...     .loc['2000-01-01':'2000-03-01']
...     .query('item == "sms"')
...     .groupby(['period','item'])
...     .agg(
...         duration_count = ('duration', 'count'),
...         duration_sum = ('duration', 'sum'),
...         duration_median = ('duration', 'median'),
...         duration_mean = ('duration', 'mean'),
...         duration_std = ('duration', 'std'),
...         duration_var = ('duration', 'var'),
...         value = ('duration', lambda column: column.mean().astype(int))
...     )
... )