tut12 zwischenspeichern
This commit is contained in:
@ -225,4 +225,95 @@ Musterlösung 11 - Wiederholung Types - Functions!
|
|||||||
|
|
||||||
## Funktionale Programmierung - was ist das?
|
## Funktionale Programmierung - was ist das?
|
||||||
|
|
||||||
-
|
- Funktionen sind äquivalent zu Datenobjekten
|
||||||
|
- anonyme Funktionen aka Lambdas
|
||||||
|
- Closures
|
||||||
|
- Programmablauf mit Verkettung und Komposition von Funktionen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Funktionen sind Datenobjekte
|
||||||
|
|
||||||
|
- Jede Funktion hat den Datentyp `Callable`
|
||||||
|
- Wir können Funktionen wie alle anderen Objekte variabeln zuweisen
|
||||||
|
```python
|
||||||
|
def add(a: int, b: int) -> int:
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
add_but_variable = add
|
||||||
|
|
||||||
|
print(add_but_variable(3, 2)) # 5
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anonyme Funktionen - `lambda`
|
||||||
|
|
||||||
|
- Mit dem `lambda` Keyword lassen sich anonyme Funktionen definieren ohne `def`
|
||||||
|
- Bietet sich vor allem an für kleine Funktionen und Kompositionen von Funktionen
|
||||||
|
```python
|
||||||
|
print(reduce(lambda x, y: x + y, [1, 2, 3, 4])) # 10
|
||||||
|
```
|
||||||
|
- hat als Datentyp auch `Callable`
|
||||||
|
```python
|
||||||
|
add: Callable[[int, int], int] = lambda x, y: x + y
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Closures
|
||||||
|
|
||||||
|
- Verkettete Funktionen, bei denen die Variabeln aus vorherigen benutzt werden können
|
||||||
|
```python
|
||||||
|
def poly(x: float) -> Callable[[float, float], Callable[[float], float]]:
|
||||||
|
return lambda a, b: lambda c: a * x ** 2 + b * x + c
|
||||||
|
|
||||||
|
print(poly(3)(2, 3)(5)) # 2 * 3 ** 2 + 3 * 3 + 5 = 32
|
||||||
|
```
|
||||||
|
- kein wirklich schönes Beispiel, ein besseres ist `compose` für Kompositionen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Komposition
|
||||||
|
|
||||||
|
- Verketten von Funktionen
|
||||||
|
```python
|
||||||
|
def compose[T](*funcs: Callable[[T], T]) -> Callable[[T], T]:
|
||||||
|
return reduce(lambda f, g: lambda n: f(g(n)), funcs)
|
||||||
|
|
||||||
|
f: Callable[[int], int] = lambda n: n + 42
|
||||||
|
g: Callable[[int], int] = lambda n: n ** 2
|
||||||
|
h: Callable[[int], int] = lambda n: n - 3
|
||||||
|
|
||||||
|
print(compose(f, g, h)(0))
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Higher-Order Functions
|
||||||
|
|
||||||
|
- nehmen eine oder mehrere `Callable` als Argument
|
||||||
|
- geben ein `Callable` zurück
|
||||||
|
|
||||||
|
### Higher-Order-Functions - `map`
|
||||||
|
|
||||||
|
- Wendet ein `Callable` auf jedes Element in einem `Iterable` an
|
||||||
|
|
||||||
|
```python
|
||||||
|
def map[T, R](func: Callable[[T], R], xs: Iterable[T]) -> Iterable[R]:
|
||||||
|
return [func(x) for x in xs]
|
||||||
|
|
||||||
|
numeric_list = list(map(lambda e: int(e), ['1', '2', '3']))
|
||||||
|
print(numeric_list) # [1, 2, 3]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Higher-Order-Functions - `filter`
|
||||||
|
|
||||||
|
- `filter` verarbeitet Datenstrukturen anhand eines Prädikats (`Callable`)
|
||||||
|
- behält nur Elemente die das Prädikat erfüllen
|
||||||
|
```python
|
||||||
|
def filter[T](predicate: Callable[[T], bool], xs: Iterable[T]) -> Iterable[T]:
|
||||||
|
return [x for x in xs if predicate(x)]
|
||||||
|
```
|
BIN
Tutorium/tut12/slides.pdf
Normal file
BIN
Tutorium/tut12/slides.pdf
Normal file
Binary file not shown.
@ -5,8 +5,8 @@ def map[T, R](func: Callable[[T], R], xs: Iterable[T]) -> Iterable[R]:
|
|||||||
return [func(x) for x in xs]
|
return [func(x) for x in xs]
|
||||||
|
|
||||||
|
|
||||||
def filter[T](func: Callable[[T], bool], xs: Iterable[T]) -> Iterable[T]:
|
def filter[T](predicate: Callable[[T], bool], xs: Iterable[T]) -> Iterable[T]:
|
||||||
return [x for x in xs if func(x)]
|
return [x for x in xs if predicate(x)]
|
||||||
|
|
||||||
|
|
||||||
def reduce[T](func: Callable[[T, T], T], xs: Iterable[T]) -> T:
|
def reduce[T](func: Callable[[T, T], T], xs: Iterable[T]) -> T:
|
||||||
@ -35,21 +35,49 @@ def compose[T](*funcs: Callable[[T], T]) -> Callable[[T], T]:
|
|||||||
return reduce(lambda f, g: lambda n: f(g(n)), funcs)
|
return reduce(lambda f, g: lambda n: f(g(n)), funcs)
|
||||||
|
|
||||||
|
|
||||||
f: Callable[[int], int] = lambda n: n + 42
|
def poly(x: float) -> Callable[[float, float], Callable[[float], float]]:
|
||||||
g: Callable[[int], int] = lambda n: n ** 2
|
return lambda a, b: lambda c: a * x ** 2 + b * x + c
|
||||||
h: Callable[[int], int] = lambda n: n - 3
|
|
||||||
|
|
||||||
print(compose(f, g, h)(0))
|
def main():
|
||||||
|
f: Callable[[int], int] = lambda n: n + 42
|
||||||
|
g: Callable[[int], int] = lambda n: n ** 2
|
||||||
|
h: Callable[[int], int] = lambda n: n - 3
|
||||||
|
|
||||||
print(list(filter(lambda e: bool(e), [1, 2, 3, None, 5, 6])))
|
fhg: Callable[[int], int] = compose(f, g, h)
|
||||||
print(list(filter(lambda e: not bool(e), [1, 2, 3, None, 5, 6])))
|
|
||||||
|
|
||||||
print(list(map(lambda e: str(e), [1, 2, 3, 4, 5, 6, "hello_functional"])))
|
# f(g(h(0))) <=> ((0 - 3) ** 2) + 42 = 52
|
||||||
|
print(fhg(0))
|
||||||
|
print(compose(f, g, h)(0))
|
||||||
|
|
||||||
print(list(
|
print(list(filter(lambda e: bool(e), [1, 2, 3, None, 5, 6])))
|
||||||
filter(lambda e: len(e) > 1,
|
print(list(filter(lambda e: not bool(e), [1, 2, 3, None, 5, 6])))
|
||||||
map(lambda e: str(e),
|
|
||||||
[1, 2, 3, 4, "hello_world"]))))
|
|
||||||
|
|
||||||
print(list(filter(lambda e: isinstance(e, int), [1, 2, 3, "hello"])))
|
print(list(map(lambda e: str(e), [1, 2, 3, 4, 5, 6, "hello_functional"])))
|
||||||
print(list(flatten([[1, 2, 3], 4, [[5, 6], 7, [8, 9]]])))
|
|
||||||
|
print(list(
|
||||||
|
filter(lambda e: len(e) > 1,
|
||||||
|
map(lambda e: str(e),
|
||||||
|
[1, 2, 3, 4, "hello_world"]))))
|
||||||
|
|
||||||
|
print(list(filter(lambda e: isinstance(e, int), [1, 2, 3, "hello"])))
|
||||||
|
print(list(flatten([[1, 2, 3], 4, [[5, 6], 7, [8, 9]]])))
|
||||||
|
|
||||||
|
def add(a: int, b: int) -> int:
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
add_but_variable: Callable[[int, int], int] = add
|
||||||
|
|
||||||
|
print(add_but_variable(3, 2)) # 5
|
||||||
|
|
||||||
|
add2: Callable[[int, int], int] = lambda x, y: x + y
|
||||||
|
|
||||||
|
print(add2(2, 3))
|
||||||
|
|
||||||
|
print((lambda x, y: x + y)(3, 4))
|
||||||
|
|
||||||
|
print(reduce(lambda x, y: x + y, [1, 2, 3, 4])) # 10
|
||||||
|
|
||||||
|
print(poly(3)(2, 3)(5))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Reference in New Issue
Block a user