|
| 1 | +--- |
| 2 | +title: |
| 3 | +- Akademia Pythona |
| 4 | +author: |
| 5 | +- IV Funkcje |
| 6 | +theme: |
| 7 | +- Copenhagen |
| 8 | +--- |
| 9 | + |
| 10 | + |
| 11 | +# KN Pythona - Kurs Pythona |
| 12 | + |
| 13 | +KN Pythona wita na kursie Pythona. |
| 14 | + |
| 15 | +Plan: |
| 16 | + |
| 17 | ++ Zaawansowane zagadnienia dotyczące funkcji |
| 18 | ++ Iteracje i składanie list - część 2. |
| 19 | + |
| 20 | + |
| 21 | +# Funkcje |
| 22 | + |
| 23 | +Koncepcje projektowania funkcji: |
| 24 | + |
| 25 | +- Sprzęganie: używanie argumentów jako danych wejściowych oraz instrukcji return do zwracania wyników. |
| 26 | +- Sprzęganie: używanie zmiennych globalnych wyłącznie tam, gdzie to konieczne. |
| 27 | +- Sprzęganie: nie należy modyfikować argumentów mutowalnych, o ile kod wywołujący tego nie oczekuje. |
| 28 | +- Spójność: każda funkcja powinna mieć jeden zunifikowanyc cel. |
| 29 | +- Rozmiar: każda funkcja powinna być relatywnie mała. |
| 30 | +- Sprzęganie: należy unikać bezpośredniego modyfikowania zmiennych zdefiniowanych w innym pliku modułu. |
| 31 | + |
| 32 | + |
| 33 | +# Funkcje rekurencyjne |
| 34 | + |
| 35 | +Sumowanie z użyciem rekurencji |
| 36 | + |
| 37 | +```python |
| 38 | +def mysum(L): |
| 39 | + if not L: |
| 40 | + return 0 |
| 41 | + else: |
| 42 | + return L[0] + mysum(L[1:]) |
| 43 | + |
| 44 | +mysum([1, 2, 3, 4, 5]) # 15 |
| 45 | +``` |
| 46 | + |
| 47 | + |
| 48 | +# Funkcje rekurencyjne |
| 49 | + |
| 50 | +Sumowanie z użyciem rekurencji |
| 51 | + |
| 52 | +```python |
| 53 | +def mysum(L): |
| 54 | + first, *rest = L |
| 55 | + return first if not L else first + mysum(rest) |
| 56 | + |
| 57 | +mysum([1, 2, 3, 4, 5]) # 15 |
| 58 | +``` |
| 59 | + |
| 60 | + |
| 61 | +# Funkcje rekurencyjne |
| 62 | + |
| 63 | +Obsługa dowolnych struktur |
| 64 | + |
| 65 | +```python |
| 66 | +def sum_tree(L): |
| 67 | + tot = 0 |
| 68 | + for x in L: |
| 69 | + if not isinstance(x, list): |
| 70 | + tot += x |
| 71 | + else: |
| 72 | + tot += sum_tree(x) |
| 73 | + return tot |
| 74 | + |
| 75 | +L = [1, [2, [3, 4], 5], 6, [7, 8]] |
| 76 | +print(sum_tree(L)) # 36 |
| 77 | +``` |
| 78 | + |
| 79 | + |
| 80 | +# Funkcje rekurencyjne |
| 81 | + |
| 82 | +```python |
| 83 | +import sys |
| 84 | +sys.setrecursionlimit(10**10) |
| 85 | +``` |
| 86 | + |
| 87 | + |
| 88 | +# Obiekty funkcji |
| 89 | + |
| 90 | +Pośrednie wywołania funkcji |
| 91 | +```python |
| 92 | +def echo(message): |
| 93 | + print(message) |
| 94 | + |
| 95 | +x = echo |
| 96 | +x('abc') # abc |
| 97 | + |
| 98 | + |
| 99 | +def indirect(func, arg): |
| 100 | + func(arg) |
| 101 | + |
| 102 | +indirect(echo, 'abc') # abc |
| 103 | +``` |
| 104 | + |
| 105 | + |
| 106 | +# Harmonogram |
| 107 | + |
| 108 | +```python |
| 109 | +schedule = [(echo, 'abc'), (echo, 'xyz')] |
| 110 | +for func, arg in schedule: |
| 111 | + func(arg) # abc, xyz |
| 112 | +``` |
| 113 | + |
| 114 | + |
| 115 | +# Introspekcja funkcji |
| 116 | + |
| 117 | +```python |
| 118 | +def func(a): |
| 119 | + b = 'abc' |
| 120 | + return b * a |
| 121 | + |
| 122 | +func(3) # 'abcabcabc' |
| 123 | +``` |
| 124 | + |
| 125 | + |
| 126 | +# Introspekcja funkcji |
| 127 | + |
| 128 | +```python |
| 129 | +func.__name__ # 'func' |
| 130 | +dir(func) |
| 131 | +func.__code__ |
| 132 | +dir(func.__code__) |
| 133 | +func.__code__.to_varnames # ('a', 'b') |
| 134 | +func.__code__.to_argcount # 1 |
| 135 | +``` |
| 136 | + |
| 137 | + |
| 138 | +# Atrybuty funkcji |
| 139 | + |
| 140 | +```python |
| 141 | +func.count = 0 |
| 142 | +func.count += 3 |
| 143 | +func.count # 3 |
| 144 | +``` |
| 145 | + |
| 146 | + |
| 147 | +# Adnotacje funkcji |
| 148 | + |
| 149 | +```python |
| 150 | +def func(a: 'expl', b: (1, 10) = 4, c: float) -> int: |
| 151 | + return a + b + c |
| 152 | + |
| 153 | +func.__annotations__ |
| 154 | +``` |
| 155 | + |
| 156 | + |
| 157 | +# Funkcje anonimowe |
| 158 | + |
| 159 | +Wyrażenia **lambda** zostały zaczerpnięte z języka LISP, który z kolei zaczerpnął je z rachunku lambda, formy logiki symbolicznej. |
| 160 | + |
| 161 | + |
| 162 | +# Funkcje anonimowe |
| 163 | + |
| 164 | +```python |
| 165 | +lambda argument1, ...: wyrażenie wykorzystujące argumenty |
| 166 | +``` |
| 167 | + |
| 168 | + |
| 169 | +# Funkcje anonimowe |
| 170 | + |
| 171 | +Funkcje anonimowe: |
| 172 | + |
| 173 | +- **lambda** jest wyrażeniem, a nie instrukcją. |
| 174 | +- Ciałem **lambda** jest pojedyńcze wyrażenie, a nie blok instrukcji. |
| 175 | + |
| 176 | + |
| 177 | +# Funkcje anonimowe |
| 178 | + |
| 179 | +```python |
| 180 | +def func(x, y, z): return x + y + z |
| 181 | + |
| 182 | +func = lambda x, y, z: x + y + z |
| 183 | + |
| 184 | +x = lambda a='raz', b='dwa', c='trzy': a + b + c |
| 185 | +x('las') # lasdwatrzy |
| 186 | +``` |
| 187 | + |
| 188 | + |
| 189 | +# Funkcje anonimowe |
| 190 | + |
| 191 | +```python |
| 192 | +def title(a): |
| 193 | + pref = a |
| 194 | + return lambda x: pref + " " + x |
| 195 | + |
| 196 | +a_func = title('abc') |
| 197 | +a_func('def') # abcdef |
| 198 | +``` |
| 199 | + |
| 200 | + |
| 201 | +# Funkcje anonimowe |
| 202 | + |
| 203 | +```python |
| 204 | +lower = lambda x, y: x if x < y else y |
| 205 | + |
| 206 | +showall = lambda x: map(sys.stdout, x) |
| 207 | + |
| 208 | +showtable = lambda x: [sys.stdout.write(line) for line in x] |
| 209 | +``` |
| 210 | + |
| 211 | + |
| 212 | +# Funkcje anonimowe |
| 213 | + |
| 214 | +```python |
| 215 | +action = (lambda x: (lambda y: x + y)) |
| 216 | + |
| 217 | +act = action(2) |
| 218 | +act(2) # 4 (2 + 2 = 4) |
| 219 | +``` |
| 220 | + |
| 221 | + |
| 222 | +# Odwzorowywanie funkcji na sekwencje - map |
| 223 | + |
| 224 | +```python |
| 225 | +counters = [1, 2, 3, 4] |
| 226 | +updated = [] |
| 227 | +for x in counters: |
| 228 | + updated.append(x + 10) |
| 229 | + |
| 230 | +updated # 11, 12, 13, 14 |
| 231 | +``` |
| 232 | + |
| 233 | + |
| 234 | +# Odwzorowywanie funkcji na sekwencje - map |
| 235 | + |
| 236 | +```python |
| 237 | +def inc(x): return x + 10 |
| 238 | + |
| 239 | +map(inc, counters) |
| 240 | + |
| 241 | +map((lambda x: x + 10), counters) |
| 242 | +``` |
| 243 | + |
| 244 | + |
| 245 | +# Narzędzia programowania funkcyjnego - filter i reduce |
| 246 | + |
| 247 | +```python |
| 248 | +filter((lambda x: x > 0), range(-100, 100)) # 1..99 |
| 249 | + |
| 250 | +from functools import reduce |
| 251 | + |
| 252 | +reduce((lambda x, y: x + y), [1, 2, 3, 4]) # 10 |
| 253 | +reduce((lambda x, y: x * y), [1, 2, 3, 4]) # 24 |
| 254 | + |
| 255 | +import operator |
| 256 | +reduce(operator.add, [1, 2, 3, 4]) # 10 |
| 257 | +``` |
| 258 | + |
| 259 | + |
| 260 | +# Listy składane kontra map |
| 261 | + |
| 262 | +```python |
| 263 | +list(map(ord, 'abcdef')) |
| 264 | + |
| 265 | +[ord(x) for x in 'abcdef'] |
| 266 | +``` |
| 267 | + |
| 268 | + |
| 269 | +# Warunki |
| 270 | + |
| 271 | +```python |
| 272 | +list(map((lambda x: x ** 2), filter((lambda x: x % 2 == 0), range(5)))) |
| 273 | + |
| 274 | +[x ** 2 for x in range(5) if not x % 2] |
| 275 | +``` |
| 276 | + |
| 277 | + |
| 278 | +# Generatory |
| 279 | + |
| 280 | +Funkcje generatorów, które tworzy się tak samo jak zwykłe funkcje, ale zamiast instrukcji **return** do zwracania wyników cząstkowych wykorzystuje się instrukcję **yield**, która zawiesza wykonanie funkcji, zachowując jej stan, co pozwala wznowić ją w przypadku, gdy odbiorca znów poprosi o dane. |
| 281 | + |
| 282 | + |
| 283 | +# Generatory |
| 284 | + |
| 285 | +Wyrażenia generatorów mają składnię zbliżoną do list składanych, ale zwracają obiekt generujący wyniki cząstkowe na żądanie, zamiast tworzyć naraz całą listę wyników. |
| 286 | + |
| 287 | + |
| 288 | +# Generatory |
| 289 | + |
| 290 | +```python |
| 291 | +def gensquares(N): |
| 292 | + for i in range(N): |
| 293 | + yield i ** 2 |
| 294 | + |
| 295 | +list(gensquares(100)) |
| 296 | +``` |
| 297 | + |
| 298 | + |
| 299 | +# Generatory a protokół iteracyjny |
| 300 | + |
| 301 | +Pętle for i inne konteksty iteracyjne wymagają obiektów implementujących interfejs iteratorów. Instrukcje **yield** kompilowane są jako generatory, które obsługują interfejs iteracji i metodę __next__ wznawiającą wykonywanie operacji. |
| 302 | + |
| 303 | + |
| 304 | + |
| 305 | +# Wyrażenia generatorów |
| 306 | + |
| 307 | +```python |
| 308 | +def times_four(S): |
| 309 | + for c in S: |
| 310 | + yield c * 4 |
| 311 | + |
| 312 | +(c * 4 for c in S) # <generator object at 0x...> |
| 313 | +``` |
0 commit comments