├── .gitignore
├── 00-zaklady.ipynb
├── 01-funkce.ipynb
├── 02-oop.ipynb
├── 03-vyjimky.ipynb
├── 04-slozky-soubory-archivy.ipynb
├── 05-generatory-iteratory.ipynb
├── 06-dobre-zvyky.ipynb
├── 07-retezce.ipynb
├── 08-formaty-souboru.ipynb
├── 09-databaze-perzistence.ipynb
├── 10-interakce-os-uzivatel.ipynb
├── 11-web.ipynb
├── Dockerfile
├── LICENSE
├── Pipfile
├── Pipfile.lock
├── README.md
├── data
├── accel.csv
├── books.j2
├── books.xml
├── books_processed.xml
├── config.ini
├── config_updated.ini
├── employees.yaml
├── employees_write.yaml
├── leave-me-alone.txt
├── menu.csv
├── package.json
├── people.db
├── pickle.p
├── slovnik.p
├── storage.db
├── widget.json
├── widget_write.json
└── write.csv
├── docker-compose.yaml
└── img
├── bloky.png
├── generators-everywhere.jpg
├── harry-python.png
├── kasna-lambda.jpg
├── logo.png
├── oop.png
└── oop_trieda_vs_objekt.png
/.gitignore:
--------------------------------------------------------------------------------
1 | .ipynb_checkpoints/
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 | venv/
--------------------------------------------------------------------------------
/01-funkce.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# Funkce"
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {
18 | "slideshow": {
19 | "slide_type": "subslide"
20 | }
21 | },
22 | "outputs": [],
23 | "source": [
24 | "def secist(x, y=0):\n",
25 | " print(\"x je {}, y je {}\".format(x, y))\n",
26 | " return x + y"
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": null,
32 | "metadata": {
33 | "slideshow": {
34 | "slide_type": "fragment"
35 | }
36 | },
37 | "outputs": [],
38 | "source": [
39 | "secist(5, 6)"
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "execution_count": null,
45 | "metadata": {
46 | "slideshow": {
47 | "slide_type": "fragment"
48 | }
49 | },
50 | "outputs": [],
51 | "source": [
52 | "# pojmenované argumenty lze předat v libovolném pořadí\n",
53 | "secist(y=6, x=5)"
54 | ]
55 | },
56 | {
57 | "cell_type": "markdown",
58 | "metadata": {
59 | "slideshow": {
60 | "slide_type": "slide"
61 | }
62 | },
63 | "source": [
64 | "## Příklad\n",
65 | "Napište funkci, která má jako parametry 3 strany trojúhelníku a vrací `True/False` podle toho, jestli je daný trojúhelník reálný (jestli platí trojúhelníhová nerovnost)."
66 | ]
67 | },
68 | {
69 | "cell_type": "code",
70 | "execution_count": null,
71 | "metadata": {},
72 | "outputs": [],
73 | "source": [
74 | "# TODO"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": null,
80 | "metadata": {},
81 | "outputs": [],
82 | "source": [
83 | "if nerovnost(1, 1, 1) == True:\n",
84 | " print(\"funguje\")\n",
85 | "if nerovnost(99, 1, 1) == False:\n",
86 | " print(\"funguje\")\n",
87 | "if nerovnost(10, 1, 1) == False:\n",
88 | " print(\"funguje\")\n",
89 | "if nerovnost(1, 2, 3) == False:\n",
90 | " print(\"funguje\")\n",
91 | "if nerovnost(2, 2, 3) == True:\n",
92 | " print(\"funguje\")"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {
98 | "slideshow": {
99 | "slide_type": "slide"
100 | }
101 | },
102 | "source": [
103 | "## Příklad\n",
104 | "\n",
105 | "Napište funkci, která *vrátí* N-tý člen Fibonacciho řady."
106 | ]
107 | },
108 | {
109 | "cell_type": "code",
110 | "execution_count": null,
111 | "metadata": {},
112 | "outputs": [],
113 | "source": [
114 | "# TODO"
115 | ]
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "metadata": {
120 | "slideshow": {
121 | "slide_type": "slide"
122 | }
123 | },
124 | "source": [
125 | "### Proměnné počty argumentů\n",
126 | "\n",
127 | "Nutno rozlišovat:\n",
128 | "- poziční = *při volání* záleží na jejich **pořadí**\n",
129 | "- pojmenované = *při volání* záleží na jejich **pojmenování**"
130 | ]
131 | },
132 | {
133 | "cell_type": "code",
134 | "execution_count": null,
135 | "metadata": {
136 | "slideshow": {
137 | "slide_type": "subslide"
138 | }
139 | },
140 | "outputs": [],
141 | "source": [
142 | "def zpracuj_posledni_soubor(*soubory): # proměnný počet pozičních\n",
143 | " return \"zpracováno: \" + soubory[-1]\n",
144 | "\n",
145 | "zpracuj_posledni_soubor('soubor1', 'soubor2', 'soubor3')"
146 | ]
147 | },
148 | {
149 | "cell_type": "code",
150 | "execution_count": null,
151 | "metadata": {
152 | "slideshow": {
153 | "slide_type": "subslide"
154 | }
155 | },
156 | "outputs": [],
157 | "source": [
158 | "def vypis_cele_jmeno(**data): # proměnný počet pojmenovaných\n",
159 | "\n",
160 | " if \"jmeno\" in data and \"prijmeni\" in data:\n",
161 | " print( \"{} {}\".format(data[\"jmeno\"], data[\"prijmeni\"]) )\n",
162 | "\n",
163 | " elif \"prijmeni\" in data:\n",
164 | " print(data[\"prijmeni\"])\n",
165 | " \n",
166 | " elif \"jmeno\" in data:\n",
167 | " print(data[\"jmeno\"])\n",
168 | " \n",
169 | " else:\n",
170 | " print(\"(neznámá osoba)\")\n",
171 | "\n",
172 | "vypis_cele_jmeno(jmeno=\"Milan\", vyska=180, vek=20, prijmeni=\"Frajer\")\n",
173 | "vypis_cele_jmeno()"
174 | ]
175 | },
176 | {
177 | "cell_type": "markdown",
178 | "metadata": {
179 | "slideshow": {
180 | "slide_type": "subslide"
181 | }
182 | },
183 | "source": [
184 | "**Konvence:**\n",
185 | "- poziční = `*args`\n",
186 | "- pojmenované = `**kwargs`"
187 | ]
188 | },
189 | {
190 | "cell_type": "code",
191 | "execution_count": null,
192 | "metadata": {
193 | "slideshow": {
194 | "slide_type": "fragment"
195 | }
196 | },
197 | "outputs": [],
198 | "source": [
199 | "# lze použít obojí najednou\n",
200 | "def vypis_vse(*args, **kwargs):\n",
201 | " print(args, kwargs) # print() vypíše všechny své parametry\n",
202 | "\n",
203 | "vypis_vse(1, 2, a=3, b=4)"
204 | ]
205 | },
206 | {
207 | "cell_type": "markdown",
208 | "metadata": {
209 | "slideshow": {
210 | "slide_type": "slide"
211 | }
212 | },
213 | "source": [
214 | "### Rozbaluju, rozbaluješ, rozbalujeme\n",
215 | "`*` nebo `**` lze použít při volání funkce k rozbalení N-tic nebo slovníků!"
216 | ]
217 | },
218 | {
219 | "cell_type": "code",
220 | "execution_count": null,
221 | "metadata": {},
222 | "outputs": [],
223 | "source": [
224 | "ntice = (1, 2, 3, 4)\n",
225 | "slovnik = {\"a\": 3, \"b\": 4}\n",
226 | "\n",
227 | "vypis_vse(ntice) # = vypis_vse((1, 2, 3, 4)) – jeden parametr, N-tice\n",
228 | "vypis_vse(*ntice) # = vypis_vse(1, 2, 3, 4) – čtyři parametry\n",
229 | "vypis_vse(**slovnik) # = vypis_vse(a=3, b=4) – dva pojmenované parametry\n",
230 | "vypis_vse(*ntice, **slovnik) # = vypis_vse(1, 2, 3, 4, a=3, b=4) – mix"
231 | ]
232 | },
233 | {
234 | "cell_type": "markdown",
235 | "metadata": {
236 | "slideshow": {
237 | "slide_type": "slide"
238 | }
239 | },
240 | "source": [
241 | "## Mini-příklad"
242 | ]
243 | },
244 | {
245 | "cell_type": "code",
246 | "execution_count": null,
247 | "metadata": {},
248 | "outputs": [],
249 | "source": [
250 | "def nastav_budik(den, hodina, minuta=0):\n",
251 | " print(\"Nastavuji budík na '{}' v '{}' hodin '{}' minut.\".format(den, hodina, minuta))\n",
252 | "\n",
253 | "\n",
254 | "pracovni_den = {\n",
255 | " \"den\": \"pondeli\",\n",
256 | " \"hodina\": 6\n",
257 | "}\n",
258 | "\n",
259 | "\n",
260 | "# TODO zavolat nastavení budíku - jak?"
261 | ]
262 | },
263 | {
264 | "cell_type": "markdown",
265 | "metadata": {
266 | "slideshow": {
267 | "slide_type": "slide"
268 | }
269 | },
270 | "source": [
271 | "### Viditelnost proměnných"
272 | ]
273 | },
274 | {
275 | "cell_type": "code",
276 | "execution_count": null,
277 | "metadata": {},
278 | "outputs": [],
279 | "source": [
280 | "# vytvořme globální proměnnou x\n",
281 | "x = 5"
282 | ]
283 | },
284 | {
285 | "cell_type": "code",
286 | "execution_count": null,
287 | "metadata": {
288 | "slideshow": {
289 | "slide_type": "fragment"
290 | }
291 | },
292 | "outputs": [],
293 | "source": [
294 | "def nastav_x(cislo):\n",
295 | " x = cislo # lokální\n",
296 | " print(x)\n",
297 | " \n",
298 | "nastav_x(42)\n",
299 | "print(x)"
300 | ]
301 | },
302 | {
303 | "cell_type": "code",
304 | "execution_count": null,
305 | "metadata": {
306 | "slideshow": {
307 | "slide_type": "fragment"
308 | }
309 | },
310 | "outputs": [],
311 | "source": [
312 | "def nastav_globalni_x(cislo):\n",
313 | " global x\n",
314 | " print(x) # lze číst už zde\n",
315 | " x = cislo # globální efekt\n",
316 | " print(x)\n",
317 | "\n",
318 | "nastav_globalni_x(6)\n",
319 | "print(x)"
320 | ]
321 | },
322 | {
323 | "cell_type": "markdown",
324 | "metadata": {
325 | "slideshow": {
326 | "slide_type": "slide"
327 | }
328 | },
329 | "source": [
330 | "## Funkce jako *first class objects*\n",
331 | "\n",
332 | "> In short, it means there are no restrictions on the object's use."
333 | ]
334 | },
335 | {
336 | "cell_type": "code",
337 | "execution_count": null,
338 | "metadata": {
339 | "slideshow": {
340 | "slide_type": "fragment"
341 | }
342 | },
343 | "outputs": [],
344 | "source": [
345 | "def secti(a, b):\n",
346 | " \"\"\"Sečte dvě čísla.\"\"\"\n",
347 | " return a + b"
348 | ]
349 | },
350 | {
351 | "cell_type": "code",
352 | "execution_count": null,
353 | "metadata": {
354 | "slideshow": {
355 | "slide_type": "subslide"
356 | }
357 | },
358 | "outputs": [],
359 | "source": [
360 | "# můžeme je volat (wow)\n",
361 | "print(secti(1, 2))\n",
362 | "\n",
363 | "# lze je aliasovat\n",
364 | "add = secti\n",
365 | "print(add(2, 5))\n",
366 | "\n",
367 | "# lze smazat původní referenci\n",
368 | "del secti\n",
369 | "print(add(10, 11))\n",
370 | "\n",
371 | "# mají atributy\n",
372 | "print(add.__doc__)\n",
373 | "\n",
374 | "# lze je přepsat jinými hodnotami\n",
375 | "add = 3\n",
376 | "print(add)"
377 | ]
378 | },
379 | {
380 | "cell_type": "markdown",
381 | "metadata": {
382 | "slideshow": {
383 | "slide_type": "slide"
384 | }
385 | },
386 | "source": [
387 | "## Uzávěry (closures)\n",
388 | "\n",
389 | "= Funkce, které si s sebou nesou *kontext*. Fungují tak např. dekorátory."
390 | ]
391 | },
392 | {
393 | "cell_type": "code",
394 | "execution_count": null,
395 | "metadata": {
396 | "slideshow": {
397 | "slide_type": "subslide"
398 | }
399 | },
400 | "outputs": [],
401 | "source": [
402 | "from random import random\n",
403 | "\n",
404 | "def vyrob_scitacku(pricitane_cislo):\n",
405 | " chyba = random()\n",
406 | "\n",
407 | " # vytvoříme uzávěru\n",
408 | " def scitacka(x):\n",
409 | " # mám k dispozici:\n",
410 | " # - `x` (parametr, dynamický)\n",
411 | " # - `chyba` (z kontextu)\n",
412 | " # - `pricitane_cislo` (z pohledu uzávěry to samé jako magicke_cislo)\n",
413 | " return x + chyba + pricitane_cislo\n",
414 | "\n",
415 | " # `scitacka` je first class object...\n",
416 | " return scitacka"
417 | ]
418 | },
419 | {
420 | "cell_type": "code",
421 | "execution_count": null,
422 | "metadata": {
423 | "slideshow": {
424 | "slide_type": "subslide"
425 | }
426 | },
427 | "outputs": [],
428 | "source": [
429 | "pricti_5 = vyrob_scitacku(5)"
430 | ]
431 | },
432 | {
433 | "cell_type": "code",
434 | "execution_count": null,
435 | "metadata": {
436 | "slideshow": {
437 | "slide_type": "fragment"
438 | }
439 | },
440 | "outputs": [],
441 | "source": [
442 | "# stále stejná \"chyba\"\n",
443 | "print(pricti_5(10))\n",
444 | "print(pricti_5(5))"
445 | ]
446 | },
447 | {
448 | "cell_type": "code",
449 | "execution_count": null,
450 | "metadata": {
451 | "slideshow": {
452 | "slide_type": "fragment"
453 | }
454 | },
455 | "outputs": [],
456 | "source": [
457 | "del vyrob_scitacku"
458 | ]
459 | },
460 | {
461 | "cell_type": "code",
462 | "execution_count": null,
463 | "metadata": {
464 | "slideshow": {
465 | "slide_type": "fragment"
466 | }
467 | },
468 | "outputs": [],
469 | "source": [
470 | "# uzávěra stále drží kontext i po smazání původní funkce\n",
471 | "pricti_5(10)"
472 | ]
473 | },
474 | {
475 | "cell_type": "markdown",
476 | "metadata": {
477 | "slideshow": {
478 | "slide_type": "slide"
479 | }
480 | },
481 | "source": [
482 | "## Dekorátor\n",
483 | "= Funkce, která dostane jako parametr jednu funkci a vrátí **libovolnou** funkci, která nahradí tu původní."
484 | ]
485 | },
486 | {
487 | "cell_type": "code",
488 | "execution_count": null,
489 | "metadata": {
490 | "slideshow": {
491 | "slide_type": "fragment"
492 | }
493 | },
494 | "outputs": [],
495 | "source": [
496 | "def samoucelny_dekorator(puvodni_fce):\n",
497 | " return puvodni_fce"
498 | ]
499 | },
500 | {
501 | "cell_type": "code",
502 | "execution_count": null,
503 | "metadata": {
504 | "slideshow": {
505 | "slide_type": "fragment"
506 | }
507 | },
508 | "outputs": [],
509 | "source": [
510 | "@samoucelny_dekorator\n",
511 | "def vypis_text(text):\n",
512 | " print(text)"
513 | ]
514 | },
515 | {
516 | "cell_type": "code",
517 | "execution_count": null,
518 | "metadata": {
519 | "slideshow": {
520 | "slide_type": "fragment"
521 | }
522 | },
523 | "outputs": [],
524 | "source": [
525 | "vypis_text(\"Ahoj\")"
526 | ]
527 | },
528 | {
529 | "cell_type": "code",
530 | "execution_count": null,
531 | "metadata": {
532 | "slideshow": {
533 | "slide_type": "subslide"
534 | }
535 | },
536 | "outputs": [],
537 | "source": [
538 | "# co se vlastně stalo:\n",
539 | "\n",
540 | "@samoucelny_dekorator\n",
541 | "def vypis_text(text):\n",
542 | " print(text)\n",
543 | "\n",
544 | "# ... je ekvivalentní ...\n",
545 | "\n",
546 | "def vypis_text(text):\n",
547 | " print(text)\n",
548 | "vypis_text = samoucelny_dekorator(vypis_text)"
549 | ]
550 | },
551 | {
552 | "cell_type": "markdown",
553 | "metadata": {
554 | "slideshow": {
555 | "slide_type": "slide"
556 | }
557 | },
558 | "source": [
559 | "### K čemu to lze využít?\n",
560 | "\n",
561 | "- nahrazení původní funkce jinou\n",
562 | "- zapsání do nějaké evidence\n",
563 | "- přidání chování před/za kód původní funkce\n",
564 | "- ... fantazii se meze nekladou ;)"
565 | ]
566 | },
567 | {
568 | "cell_type": "code",
569 | "execution_count": null,
570 | "metadata": {
571 | "slideshow": {
572 | "slide_type": "subslide"
573 | }
574 | },
575 | "outputs": [],
576 | "source": [
577 | "# nahrazení původní funkce jinou\n",
578 | "\n",
579 | "def nahrad(puvodni_fce):\n",
580 | "\n",
581 | " def podstrcena_fce():\n",
582 | " print(\"Je to kampaň, účelovka!\")\n",
583 | "\n",
584 | " return podstrcena_fce"
585 | ]
586 | },
587 | {
588 | "cell_type": "code",
589 | "execution_count": null,
590 | "metadata": {
591 | "slideshow": {
592 | "slide_type": "fragment"
593 | }
594 | },
595 | "outputs": [],
596 | "source": [
597 | "@nahrad\n",
598 | "def pozdrav():\n",
599 | " print(\"Ahoj\")\n",
600 | "\n",
601 | "pozdrav()"
602 | ]
603 | },
604 | {
605 | "cell_type": "code",
606 | "execution_count": null,
607 | "metadata": {
608 | "slideshow": {
609 | "slide_type": "subslide"
610 | }
611 | },
612 | "outputs": [],
613 | "source": [
614 | "# zapsání do nějaké evidence\n",
615 | "\n",
616 | "zavolat_pri_ukonceni = []\n",
617 | "\n",
618 | "def nakonec(fce):\n",
619 | " zavolat_pri_ukonceni.append(fce)\n",
620 | " return fce\n",
621 | "\n",
622 | "def konec_programu():\n",
623 | " for fce in zavolat_pri_ukonceni:\n",
624 | " fce()"
625 | ]
626 | },
627 | {
628 | "cell_type": "code",
629 | "execution_count": null,
630 | "metadata": {
631 | "slideshow": {
632 | "slide_type": "fragment"
633 | }
634 | },
635 | "outputs": [],
636 | "source": [
637 | "@nakonec\n",
638 | "def rozluc_se():\n",
639 | " print(\"Děkujeme za použití programu!\")\n",
640 | "\n",
641 | "@nakonec\n",
642 | "def uzavri_soubory():\n",
643 | " print(\"Uzavírám používané soubory...\")\n",
644 | "\n",
645 | "konec_programu()"
646 | ]
647 | },
648 | {
649 | "cell_type": "markdown",
650 | "metadata": {
651 | "slideshow": {
652 | "slide_type": "slide"
653 | }
654 | },
655 | "source": [
656 | "## Příklad\n",
657 | "\n",
658 | "Napište dekorátor `stopky`, který změří čas potřebný pro vykonání funkce a vypíše ho.\n",
659 | "\n",
660 | "- Vytvořte dekorátor, který nic neměří, ale volá původní funkci (předpokládejte bezparametrickou fci).\n",
661 | "- Přidejte měření.\n",
662 | "- Doplňte dekorátor tak, aby zvládal libovolně parametrické funkce.\n",
663 | "- **Hardcore:** Upravte vše tak, aby *dekorátor byl parametrický*.\n",
664 | "- **Super-hardcore:** Upravte vše tak, aby fungovala parametrická i neparametrická varianta."
665 | ]
666 | },
667 | {
668 | "cell_type": "raw",
669 | "metadata": {
670 | "slideshow": {
671 | "slide_type": "skip"
672 | }
673 | },
674 | "source": [
675 | "# hardcore varianta\n",
676 | "\n",
677 | "@stopky(30) # automaticky opakuje měření 30x, výsledek průměruje\n",
678 | "def merena_fce(...):\n",
679 | " ..."
680 | ]
681 | },
682 | {
683 | "cell_type": "code",
684 | "execution_count": null,
685 | "metadata": {
686 | "slideshow": {
687 | "slide_type": "skip"
688 | }
689 | },
690 | "outputs": [],
691 | "source": [
692 | "from time import perf_counter\n",
693 | "from datetime import timedelta\n",
694 | "\n",
695 | "\n",
696 | "# ukázka měření času\n",
697 | "\n",
698 | "start = perf_counter()\n",
699 | "\n",
700 | "x = \"hello\"\n",
701 | "\n",
702 | "end = perf_counter()\n",
703 | "diff = timedelta(seconds=end-start)\n",
704 | "print(diff)"
705 | ]
706 | },
707 | {
708 | "cell_type": "code",
709 | "execution_count": null,
710 | "metadata": {
711 | "slideshow": {
712 | "slide_type": "skip"
713 | }
714 | },
715 | "outputs": [],
716 | "source": [
717 | "# TODO implementovat stopky\n",
718 | "\n",
719 | "\n",
720 | "# TODO přidat dekorátor\n",
721 | "def bez_parametru():\n",
722 | " \"\"\"Udělá hrozně nefektivní operaci.\"\"\"\n",
723 | " x = \"\"\n",
724 | " for i in range(1000000):\n",
725 | " x += str(i) + \" \"\n",
726 | "\n",
727 | "# TODO přidat dekorátor\n",
728 | "def s_parametrem(kolikrat):\n",
729 | " \"\"\"Udělá hrozně nefektivní operaci kolikrát chcete.\"\"\"\n",
730 | " x = \"\"\n",
731 | " for i in range(kolikrat):\n",
732 | " x += str(i) + \" \""
733 | ]
734 | },
735 | {
736 | "cell_type": "code",
737 | "execution_count": null,
738 | "metadata": {
739 | "slideshow": {
740 | "slide_type": "skip"
741 | }
742 | },
743 | "outputs": [],
744 | "source": [
745 | "bez_parametru()"
746 | ]
747 | },
748 | {
749 | "cell_type": "code",
750 | "execution_count": null,
751 | "metadata": {
752 | "slideshow": {
753 | "slide_type": "skip"
754 | }
755 | },
756 | "outputs": [],
757 | "source": [
758 | "s_parametrem(1000000)"
759 | ]
760 | },
761 | {
762 | "cell_type": "code",
763 | "execution_count": null,
764 | "metadata": {
765 | "slideshow": {
766 | "slide_type": "skip"
767 | }
768 | },
769 | "outputs": [],
770 | "source": [
771 | "print(bez_parametru.__doc__)"
772 | ]
773 | },
774 | {
775 | "cell_type": "markdown",
776 | "metadata": {
777 | "slideshow": {
778 | "slide_type": "slide"
779 | }
780 | },
781 | "source": [
782 | "# Lambda funkce\n",
783 | "\n",
784 | "= Bezejmenné funkce *na jeden řádek*, automatický `return`."
785 | ]
786 | },
787 | {
788 | "cell_type": "code",
789 | "execution_count": null,
790 | "metadata": {
791 | "slideshow": {
792 | "slide_type": "-"
793 | }
794 | },
795 | "outputs": [],
796 | "source": [
797 | "lambda x: x ** 2"
798 | ]
799 | },
800 | {
801 | "cell_type": "markdown",
802 | "metadata": {
803 | "slideshow": {
804 | "slide_type": "subslide"
805 | }
806 | },
807 | "source": [
808 | "### Široké použití\n",
809 | "\n",
810 | "Uzávěry, `filter`, `map`, řazení, callbacky, ..."
811 | ]
812 | },
813 | {
814 | "cell_type": "markdown",
815 | "metadata": {
816 | "slideshow": {
817 | "slide_type": "fragment"
818 | }
819 | },
820 | "source": [
821 | ""
822 | ]
823 | },
824 | {
825 | "cell_type": "markdown",
826 | "metadata": {
827 | "slideshow": {
828 | "slide_type": "slide"
829 | }
830 | },
831 | "source": [
832 | "### Uzávěra pomocí lambdy"
833 | ]
834 | },
835 | {
836 | "cell_type": "code",
837 | "execution_count": null,
838 | "metadata": {
839 | "slideshow": {
840 | "slide_type": "fragment"
841 | }
842 | },
843 | "outputs": [],
844 | "source": [
845 | "# výše uvedené ještě jednou\n",
846 | "def vyrob_scitacku(pricitane_cislo):\n",
847 | " chyba = random()\n",
848 | " return (lambda x: x + chyba + pricitane_cislo)\n",
849 | "\n",
850 | "base_of_the_universe = vyrob_scitacku(42)\n",
851 | "base_of_the_universe(2)"
852 | ]
853 | },
854 | {
855 | "cell_type": "markdown",
856 | "metadata": {
857 | "slideshow": {
858 | "slide_type": "slide"
859 | }
860 | },
861 | "source": [
862 | "### `map`\n",
863 | "\n",
864 | "Vrátí novou sekvenci na základě staré, kde *na každý prvek aplikuje funkci*.\n",
865 | "\n",
866 | "### `filter`\n",
867 | "\n",
868 | "Vrátí novou sekvenci na základě staré, kde na každý prvek aplikuje *funkci, která rozhodne o přítomnosti* prvku v nové sekvenci."
869 | ]
870 | },
871 | {
872 | "cell_type": "code",
873 | "execution_count": null,
874 | "metadata": {
875 | "slideshow": {
876 | "slide_type": "subslide"
877 | }
878 | },
879 | "outputs": [],
880 | "source": [
881 | "data = [1, 2, 8, 5, 0, 4, 7]"
882 | ]
883 | },
884 | {
885 | "cell_type": "code",
886 | "execution_count": null,
887 | "metadata": {
888 | "slideshow": {
889 | "slide_type": "-"
890 | }
891 | },
892 | "outputs": [],
893 | "source": [
894 | "# filtrování bez lambdy\n",
895 | "def je_sude(x):\n",
896 | " return (x % 2) == 0\n",
897 | "\n",
898 | "list(filter(je_sude, data))"
899 | ]
900 | },
901 | {
902 | "cell_type": "code",
903 | "execution_count": null,
904 | "metadata": {
905 | "slideshow": {
906 | "slide_type": "fragment"
907 | }
908 | },
909 | "outputs": [],
910 | "source": [
911 | "# s lambdou\n",
912 | "list(filter(lambda x: x % 2 == 0, data))"
913 | ]
914 | },
915 | {
916 | "cell_type": "code",
917 | "execution_count": null,
918 | "metadata": {
919 | "slideshow": {
920 | "slide_type": "fragment"
921 | }
922 | },
923 | "outputs": [],
924 | "source": [
925 | "# mapování s lambdou\n",
926 | "list(map(lambda x: x ** 2, data))"
927 | ]
928 | },
929 | {
930 | "cell_type": "markdown",
931 | "metadata": {
932 | "slideshow": {
933 | "slide_type": "slide"
934 | }
935 | },
936 | "source": [
937 | "### `sorted`\n",
938 | "\n",
939 | "Vrátí novou sekvenci seřazenou buď výchozím způsobem, nebo podle *výstupu z funkce, která vrací \"řadící klíč\"*."
940 | ]
941 | },
942 | {
943 | "cell_type": "code",
944 | "execution_count": null,
945 | "metadata": {
946 | "slideshow": {
947 | "slide_type": "subslide"
948 | }
949 | },
950 | "outputs": [],
951 | "source": [
952 | "jmena = [\"Zita\", \"Adam\", \"Dan\"]\n",
953 | "sorted(jmena)"
954 | ]
955 | },
956 | {
957 | "cell_type": "code",
958 | "execution_count": null,
959 | "metadata": {
960 | "slideshow": {
961 | "slide_type": "fragment"
962 | }
963 | },
964 | "outputs": [],
965 | "source": [
966 | "# alternativní řadící klíč\n",
967 | "def posledni_pismeno(text):\n",
968 | " return text[-1]\n",
969 | "\n",
970 | "sorted(jmena, key=posledni_pismeno)"
971 | ]
972 | },
973 | {
974 | "cell_type": "code",
975 | "execution_count": null,
976 | "metadata": {
977 | "slideshow": {
978 | "slide_type": "fragment"
979 | }
980 | },
981 | "outputs": [],
982 | "source": [
983 | "# s lambdou mnohem elegantnější\n",
984 | "sorted(jmena, key=lambda jmeno: jmeno[-1])"
985 | ]
986 | },
987 | {
988 | "cell_type": "markdown",
989 | "metadata": {
990 | "slideshow": {
991 | "slide_type": "slide"
992 | }
993 | },
994 | "source": [
995 | "## Anti-patterns – aneb co NEdělat"
996 | ]
997 | },
998 | {
999 | "cell_type": "code",
1000 | "execution_count": null,
1001 | "metadata": {
1002 | "slideshow": {
1003 | "slide_type": "subslide"
1004 | }
1005 | },
1006 | "outputs": [],
1007 | "source": [
1008 | "# NE - vyrábět z lambdy běžnou funkci\n",
1009 | "na_druhou = lambda x: x ** 2\n",
1010 | "na_druhou(4)"
1011 | ]
1012 | },
1013 | {
1014 | "cell_type": "code",
1015 | "execution_count": null,
1016 | "metadata": {
1017 | "slideshow": {
1018 | "slide_type": "fragment"
1019 | }
1020 | },
1021 | "outputs": [],
1022 | "source": [
1023 | "# lepší - pokud vím, že ji budu používat opakovaně\n",
1024 | "def na_druhou(x):\n",
1025 | " return x ** 2\n",
1026 | "\n",
1027 | "na_druhou(4)"
1028 | ]
1029 | },
1030 | {
1031 | "cell_type": "code",
1032 | "execution_count": null,
1033 | "metadata": {
1034 | "slideshow": {
1035 | "slide_type": "subslide"
1036 | }
1037 | },
1038 | "outputs": [],
1039 | "source": [
1040 | "# NE - vnořené lambdy\n",
1041 | "vzorky = [\n",
1042 | " (3, 12, 90),\n",
1043 | " (2, 12, 88),\n",
1044 | " (2, 11, 97),\n",
1045 | "]\n",
1046 | "sorted(vzorky, key=lambda vzorek: max(filter(lambda x: x % 2 == 0, vzorek)))"
1047 | ]
1048 | },
1049 | {
1050 | "cell_type": "code",
1051 | "execution_count": null,
1052 | "metadata": {
1053 | "slideshow": {
1054 | "slide_type": "fragment"
1055 | }
1056 | },
1057 | "outputs": [],
1058 | "source": [
1059 | "# lepší (používá definici `je_sude` výše)\n",
1060 | "sorted(vzorky, key=lambda vzorek: max(filter(je_sude, vzorek)))"
1061 | ]
1062 | },
1063 | {
1064 | "cell_type": "code",
1065 | "execution_count": null,
1066 | "metadata": {
1067 | "slideshow": {
1068 | "slide_type": "fragment"
1069 | }
1070 | },
1071 | "outputs": [],
1072 | "source": [
1073 | "# nejlepší\n",
1074 | "def max_sude(data):\n",
1075 | " return max(filter(je_sude, data))\n",
1076 | "\n",
1077 | "sorted(vzorky, key=max_sude)"
1078 | ]
1079 | },
1080 | {
1081 | "cell_type": "markdown",
1082 | "metadata": {
1083 | "slideshow": {
1084 | "slide_type": "slide"
1085 | }
1086 | },
1087 | "source": [
1088 | "## Příklad\n",
1089 | "\n",
1090 | "Napište lambda funkci, která po předání do `sorted` *zamíchá* řazená data."
1091 | ]
1092 | },
1093 | {
1094 | "cell_type": "code",
1095 | "execution_count": null,
1096 | "metadata": {
1097 | "slideshow": {
1098 | "slide_type": "-"
1099 | }
1100 | },
1101 | "outputs": [],
1102 | "source": [
1103 | "chceme_zamichat = list(range(20))\n",
1104 | "\n",
1105 | "# TODO"
1106 | ]
1107 | },
1108 | {
1109 | "cell_type": "markdown",
1110 | "metadata": {
1111 | "slideshow": {
1112 | "slide_type": "skip"
1113 | }
1114 | },
1115 | "source": [
1116 | "Zdroje obrázků:\n",
1117 | "- http://plzensky.denik.cz/zpravy_region/zlate-kasny-na-namesti-i-po-sesti-letech-stale-budi-vasne-20160513.html"
1118 | ]
1119 | }
1120 | ],
1121 | "metadata": {
1122 | "kernelspec": {
1123 | "display_name": "Python 3",
1124 | "language": "python",
1125 | "name": "python3"
1126 | },
1127 | "language_info": {
1128 | "codemirror_mode": {
1129 | "name": "ipython",
1130 | "version": 3
1131 | },
1132 | "file_extension": ".py",
1133 | "mimetype": "text/x-python",
1134 | "name": "python",
1135 | "nbconvert_exporter": "python",
1136 | "pygments_lexer": "ipython3",
1137 | "version": "3.6.4"
1138 | }
1139 | },
1140 | "nbformat": 4,
1141 | "nbformat_minor": 1
1142 | }
1143 |
--------------------------------------------------------------------------------
/03-vyjimky.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# Výjimky\n",
12 | "\n",
13 | "> *Výjimka* (z angličtiny Exception) je v informatice chápána jako výjimečná situace, která může nastat za běhu programu."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {
20 | "slideshow": {
21 | "slide_type": "subslide"
22 | }
23 | },
24 | "outputs": [],
25 | "source": [
26 | "ouha"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {
32 | "slideshow": {
33 | "slide_type": "-"
34 | }
35 | },
36 | "source": [
37 | "**Lze vyčíst:**\n",
38 | "\n",
39 | "- typ\n",
40 | "- popis\n",
41 | "- call stack (soubory, řádky)"
42 | ]
43 | },
44 | {
45 | "cell_type": "markdown",
46 | "metadata": {
47 | "slideshow": {
48 | "slide_type": "slide"
49 | }
50 | },
51 | "source": [
52 | "## Zachycení a ošetření výjimek"
53 | ]
54 | },
55 | {
56 | "cell_type": "code",
57 | "execution_count": null,
58 | "metadata": {},
59 | "outputs": [],
60 | "source": [
61 | "try:\n",
62 | " x = 0 # << načteno od uživatele\n",
63 | " y = 6 / x\n",
64 | "\n",
65 | "except ZeroDivisionError:\n",
66 | " print(\"Nelze dělit nulou.\")"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": null,
72 | "metadata": {
73 | "slideshow": {
74 | "slide_type": "subslide"
75 | }
76 | },
77 | "outputs": [],
78 | "source": [
79 | "try:\n",
80 | " ouha\n",
81 | "\n",
82 | "except NameError as e:\n",
83 | " print(\"Proměnná neexistuje:\", e)\n",
84 | "\n",
85 | "except ZeroDivisionError:\n",
86 | " print(\"Nelze dělit nulou.\")\n",
87 | " \n",
88 | "except:\n",
89 | " print(\"Nastala nějaká chyba.\")"
90 | ]
91 | },
92 | {
93 | "cell_type": "code",
94 | "execution_count": null,
95 | "metadata": {
96 | "slideshow": {
97 | "slide_type": "subslide"
98 | }
99 | },
100 | "outputs": [],
101 | "source": [
102 | "# méně používaná syntaxe\n",
103 | "try:\n",
104 | " ouha\n",
105 | "\n",
106 | "except (ZeroDivisionError, OSError, Exception):\n",
107 | " print(\"Nastala jedna z mnoha výjimek.\")\n",
108 | "\n",
109 | "else:\n",
110 | " print(\"Blok try proběhl bez chyby.\")\n",
111 | "\n",
112 | "finally:\n",
113 | " print(\"Vypíšu se vždy!\")"
114 | ]
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {
119 | "collapsed": true,
120 | "slideshow": {
121 | "slide_type": "slide"
122 | }
123 | },
124 | "source": [
125 | "## Umělé vyvolání výjimky"
126 | ]
127 | },
128 | {
129 | "cell_type": "code",
130 | "execution_count": null,
131 | "metadata": {
132 | "slideshow": {
133 | "slide_type": "-"
134 | }
135 | },
136 | "outputs": [],
137 | "source": [
138 | "raise ValueError(\"Nesprávná hodnota.\")"
139 | ]
140 | },
141 | {
142 | "cell_type": "code",
143 | "execution_count": null,
144 | "metadata": {
145 | "slideshow": {
146 | "slide_type": "subslide"
147 | }
148 | },
149 | "outputs": [],
150 | "source": [
151 | "# ošetřím a pošlu dál\n",
152 | "try:\n",
153 | " raise ValueError(\"Nesprávná hodnota.\")\n",
154 | " \n",
155 | "except ValueError:\n",
156 | " print(\"Něco se porouchalo...\")\n",
157 | " raise"
158 | ]
159 | },
160 | {
161 | "cell_type": "code",
162 | "execution_count": null,
163 | "metadata": {
164 | "slideshow": {
165 | "slide_type": "subslide"
166 | }
167 | },
168 | "outputs": [],
169 | "source": [
170 | "# ošetřím, změním typ uvnitř zachycení a pošlu dál\n",
171 | "try:\n",
172 | " raise FileNotFoundError(\"Soubor neexistuje.\")\n",
173 | " \n",
174 | "except FileNotFoundError as e:\n",
175 | " raise ValueError(\"Zadal jste špatné jméno souboru.\") from e"
176 | ]
177 | },
178 | {
179 | "cell_type": "markdown",
180 | "metadata": {
181 | "slideshow": {
182 | "slide_type": "slide"
183 | }
184 | },
185 | "source": [
186 | "# Příklad\n",
187 | "\n",
188 | "- Načtěte od uživatele poloměr kruhu a vypočtěte jeho obsah.\n",
189 | "- Pokud nezadá číslo, přinuťte ho opakovat zadání.\n",
190 | "- Pokud zadá záporné číslo, vyhoďte výjimku `ArithmeticError`."
191 | ]
192 | },
193 | {
194 | "cell_type": "code",
195 | "execution_count": null,
196 | "metadata": {
197 | "slideshow": {
198 | "slide_type": "skip"
199 | }
200 | },
201 | "outputs": [],
202 | "source": [
203 | "# TODO"
204 | ]
205 | },
206 | {
207 | "cell_type": "markdown",
208 | "metadata": {
209 | "slideshow": {
210 | "slide_type": "slide"
211 | }
212 | },
213 | "source": [
214 | "## Všechno je objekt...\n",
215 | "\n",
216 | "Výjimka je také objekt – vestavěné výjimky používají *dědičnost* a [je jich celá flotila](https://docs.python.org/3/library/exceptions.html#exception-hierarchy).\n",
217 | "\n",
218 | "```\n",
219 | "BaseException\n",
220 | " +-- SystemExit\n",
221 | " +-- KeyboardInterrupt\n",
222 | " +-- GeneratorExit\n",
223 | " +-- Exception\n",
224 | " +-- StopIteration\n",
225 | " +-- StopAsyncIteration\n",
226 | " +-- ArithmeticError\n",
227 | " | +-- FloatingPointError\n",
228 | " | +-- OverflowError\n",
229 | " | +-- ZeroDivisionError\n",
230 | " +-- AssertionError\n",
231 | " +-- AttributeError\n",
232 | " +-- BufferError\n",
233 | " +-- EOFError\n",
234 | " +-- ImportError\n",
235 | " +-- LookupError\n",
236 | " | +-- IndexError\n",
237 | " | +-- KeyError\n",
238 | " +-- MemoryError\n",
239 | " +-- NameError\n",
240 | " | +-- UnboundLocalError\n",
241 | " +-- OSError\n",
242 | " | +-- BlockingIOError\n",
243 | " | +-- ChildProcessError\n",
244 | " | +-- ConnectionError\n",
245 | " | | +-- BrokenPipeError\n",
246 | " | | +-- ConnectionAbortedError\n",
247 | " | | +-- ConnectionRefusedError\n",
248 | " | | +-- ConnectionResetError\n",
249 | " | +-- FileExistsError\n",
250 | " | +-- FileNotFoundError\n",
251 | " | +-- InterruptedError\n",
252 | " | +-- IsADirectoryError\n",
253 | " | +-- NotADirectoryError\n",
254 | " | +-- PermissionError\n",
255 | " | +-- ProcessLookupError\n",
256 | " | +-- TimeoutError\n",
257 | " +-- ReferenceError\n",
258 | " +-- RuntimeError\n",
259 | " | +-- NotImplementedError\n",
260 | " | +-- RecursionError\n",
261 | " +-- SyntaxError\n",
262 | " | +-- IndentationError\n",
263 | " | +-- TabError\n",
264 | " +-- SystemError\n",
265 | " +-- TypeError\n",
266 | " +-- ValueError\n",
267 | " | +-- UnicodeError\n",
268 | " | +-- UnicodeDecodeError\n",
269 | " | +-- UnicodeEncodeError\n",
270 | " | +-- UnicodeTranslateError\n",
271 | " +-- Warning\n",
272 | " +-- DeprecationWarning\n",
273 | " +-- PendingDeprecationWarning\n",
274 | " +-- RuntimeWarning\n",
275 | " +-- SyntaxWarning\n",
276 | " +-- UserWarning\n",
277 | " +-- FutureWarning\n",
278 | " +-- ImportWarning\n",
279 | " +-- UnicodeWarning\n",
280 | " +-- BytesWarning\n",
281 | " +-- ResourceWarning\n",
282 | "```"
283 | ]
284 | },
285 | {
286 | "cell_type": "markdown",
287 | "metadata": {
288 | "slideshow": {
289 | "slide_type": "subslide"
290 | }
291 | },
292 | "source": [
293 | "Zachytávání díky tomu funguje hierarchicky."
294 | ]
295 | },
296 | {
297 | "cell_type": "code",
298 | "execution_count": null,
299 | "metadata": {
300 | "slideshow": {
301 | "slide_type": "-"
302 | }
303 | },
304 | "outputs": [],
305 | "source": [
306 | "try:\n",
307 | " x = 12 / 0 # vyvolá ZeroDivisionError\n",
308 | "\n",
309 | "except ArithmeticError:\n",
310 | " print(\"Chyba výpočtu.\")"
311 | ]
312 | },
313 | {
314 | "cell_type": "markdown",
315 | "metadata": {
316 | "slideshow": {
317 | "slide_type": "subslide"
318 | }
319 | },
320 | "source": [
321 | "## Vlastní výjimka\n",
322 | "\n",
323 | "Stačí odědit od nějaké standardní, významově blízké. Konvence názvu: `CokolivError`."
324 | ]
325 | },
326 | {
327 | "cell_type": "code",
328 | "execution_count": null,
329 | "metadata": {
330 | "slideshow": {
331 | "slide_type": "-"
332 | }
333 | },
334 | "outputs": [],
335 | "source": [
336 | "class NalezenSprostyTextError(ValueError):\n",
337 | " \n",
338 | " def __init__(self, slovo):\n",
339 | " self.slovo = slovo"
340 | ]
341 | },
342 | {
343 | "cell_type": "code",
344 | "execution_count": null,
345 | "metadata": {
346 | "slideshow": {
347 | "slide_type": "fragment"
348 | }
349 | },
350 | "outputs": [],
351 | "source": [
352 | "# se zachycenou výjimkou lze pracovat jako s objektem\n",
353 | "try:\n",
354 | " raise NalezenSprostyTextError(\"hrome\")\n",
355 | "\n",
356 | "except NalezenSprostyTextError as zachycena_vyjimka:\n",
357 | " print(\"Sprosťárny jako '{}' tady nestrpíme!\".format(zachycena_vyjimka.slovo))"
358 | ]
359 | },
360 | {
361 | "cell_type": "markdown",
362 | "metadata": {
363 | "slideshow": {
364 | "slide_type": "slide"
365 | }
366 | },
367 | "source": [
368 | "# Aserce\n",
369 | "\n",
370 | "> Výraz (slovo) aserce má tyto významy:\n",
371 | "> - tvrzení, prosazování\n",
372 | "> - uznání pravdivosti výroku\n",
373 | "\n",
374 | "= Zajištění, že se věci dějí očekávaným způsobem. Použití:\n",
375 | "\n",
376 | "- při vývoji,\n",
377 | "- při testování,\n",
378 | "- *NE* pro kontrolu uživatelských dat – dají se totiž vypnout."
379 | ]
380 | },
381 | {
382 | "cell_type": "code",
383 | "execution_count": null,
384 | "metadata": {
385 | "slideshow": {
386 | "slide_type": "subslide"
387 | }
388 | },
389 | "outputs": [],
390 | "source": [
391 | "# syntaxe\n",
392 | "assert 1 + 2 == 3, \"Matematika je rozbitá!\""
393 | ]
394 | },
395 | {
396 | "cell_type": "code",
397 | "execution_count": null,
398 | "metadata": {
399 | "slideshow": {
400 | "slide_type": "fragment"
401 | }
402 | },
403 | "outputs": [],
404 | "source": [
405 | "# nepravdivá aserce vyvolá výjimku\n",
406 | "assert \"KSČM - S lidmi pro lidi\" is True, \"Nemám vykládat lži.\""
407 | ]
408 | },
409 | {
410 | "cell_type": "code",
411 | "execution_count": null,
412 | "metadata": {
413 | "slideshow": {
414 | "slide_type": "subslide"
415 | }
416 | },
417 | "outputs": [],
418 | "source": [
419 | "# typické použití\n",
420 | "def vrat_posledni_prvek(data):\n",
421 | " assert data, \"Nelze pracovat bez dat.\"\n",
422 | " return data[-1]\n",
423 | "\n",
424 | "vrat_posledni_prvek(\"\")"
425 | ]
426 | },
427 | {
428 | "cell_type": "markdown",
429 | "metadata": {
430 | "slideshow": {
431 | "slide_type": "subslide"
432 | }
433 | },
434 | "source": [
435 | "Aserce je správně použitá, když jsem na základě znalosti:\n",
436 | "\n",
437 | "- kódu,\n",
438 | "- tracebacku,\n",
439 | "- a textu výjimky\n",
440 | "\n",
441 | "ihned schopen určit, *proč* a *kde* se chyba stala."
442 | ]
443 | },
444 | {
445 | "cell_type": "markdown",
446 | "metadata": {
447 | "slideshow": {
448 | "slide_type": "slide"
449 | }
450 | },
451 | "source": [
452 | "# Příklad\n",
453 | "\n",
454 | "- Vytvořte 3 třídy vlastních výjimek: `SpatnePocasiError`, `VysokeTeplotyError`, `DestivePocasiError`, použijte dědičnost.\n",
455 | "- Vytvořte soubor `aktualni-pocasi.txt` s textem: `bouřky`.\n",
456 | "- Otevřete soubor (použijte kontextový manažer), ošetřete možné výjimky, načtěte jeho obsah.\n",
457 | "- Přesvědčte se, že obsahuje právě jedno slovo (použijte aserci).\n",
458 | "- Pokud je počasí špatné, vyvolejte příslušnou výjimku.\n",
459 | "- Ošetřete výjimku pomocí společného rodiče."
460 | ]
461 | },
462 | {
463 | "cell_type": "code",
464 | "execution_count": null,
465 | "metadata": {
466 | "slideshow": {
467 | "slide_type": "-"
468 | }
469 | },
470 | "outputs": [],
471 | "source": [
472 | "# TODO nahraďte definicí tříd\n",
473 | "DestivePocasiError = None\n",
474 | "VysokeTeplotyError = None\n",
475 | "\n",
476 | "SPATNE_POCASI = {\n",
477 | " \"vysoké teploty\": VysokeTeplotyError,\n",
478 | " \"velmi vysoké teploty\": VysokeTeplotyError,\n",
479 | " \"déšť\": DestivePocasiError,\n",
480 | " \"silný déšť\": DestivePocasiError,\n",
481 | " \"kroupy\": DestivePocasiError,\n",
482 | " \"bouřky\": DestivePocasiError,\n",
483 | "}\n",
484 | "\n",
485 | "def jdi_ven():\n",
486 | " # TODO doplňte načtení počasí\n",
487 | " ...\n",
488 | " \n",
489 | "# TODO doplňte ošetření výjimky\n",
490 | "jdi_ven()"
491 | ]
492 | }
493 | ],
494 | "metadata": {
495 | "kernelspec": {
496 | "display_name": "Python 3",
497 | "language": "python",
498 | "name": "python3"
499 | },
500 | "language_info": {
501 | "codemirror_mode": {
502 | "name": "ipython",
503 | "version": 3
504 | },
505 | "file_extension": ".py",
506 | "mimetype": "text/x-python",
507 | "name": "python",
508 | "nbconvert_exporter": "python",
509 | "pygments_lexer": "ipython3",
510 | "version": "3.6.4"
511 | }
512 | },
513 | "nbformat": 4,
514 | "nbformat_minor": 1
515 | }
516 |
--------------------------------------------------------------------------------
/04-slozky-soubory-archivy.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# Soubory"
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {
18 | "slideshow": {
19 | "slide_type": "-"
20 | }
21 | },
22 | "outputs": [],
23 | "source": [
24 | "open(\"data/leave-me-alone.txt\", mode=\"r\", encoding=\"utf8\")"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {
30 | "slideshow": {
31 | "slide_type": "fragment"
32 | }
33 | },
34 | "source": [
35 | "*Vždy* uvádějte `encoding` (pro textové soubory). Python toho [zkousne spostu](https://docs.python.org/3/library/codecs.html#standard-encodings): `utf8` = `utf-8` = `UTF8` = `U8`."
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "metadata": {
41 | "slideshow": {
42 | "slide_type": "subslide"
43 | }
44 | },
45 | "source": [
46 | "## Jak pracovat s otevřenými soubory?"
47 | ]
48 | },
49 | {
50 | "cell_type": "code",
51 | "execution_count": null,
52 | "metadata": {
53 | "slideshow": {
54 | "slide_type": "-"
55 | }
56 | },
57 | "outputs": [],
58 | "source": [
59 | "# problém?\n",
60 | "f = open(\"data/leave-me-alone.txt\")\n",
61 | "f.read()\n",
62 | "f.close()"
63 | ]
64 | },
65 | {
66 | "cell_type": "code",
67 | "execution_count": null,
68 | "metadata": {
69 | "slideshow": {
70 | "slide_type": "fragment"
71 | }
72 | },
73 | "outputs": [],
74 | "source": [
75 | "try:\n",
76 | " f = open(\"data/leave-me-alone.txt\")\n",
77 | " f.read()\n",
78 | "finally:\n",
79 | " f.close()"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": null,
85 | "metadata": {
86 | "slideshow": {
87 | "slide_type": "fragment"
88 | }
89 | },
90 | "outputs": [],
91 | "source": [
92 | "with open(\"data/leave-me-alone.txt\") as f:\n",
93 | " f.read()"
94 | ]
95 | },
96 | {
97 | "cell_type": "markdown",
98 | "metadata": {
99 | "slideshow": {
100 | "slide_type": "subslide"
101 | }
102 | },
103 | "source": [
104 | "### [Módy otevření](https://docs.python.org/3/library/functions.html#open)\n",
105 | "\n",
106 | "- `r` = read = čtení\n",
107 | "- `w` = write = zápis (smaže existující data)\n",
108 | "- `a` = append = přidávání (zápis za existující obsah)\n",
109 | "- `b` = binary = binární režim (jediná možnost vynechat kódování)\n",
110 | "- `+` = čtení i zápis\n",
111 | "- módy lze kombinovat (`wb+`)"
112 | ]
113 | },
114 | {
115 | "cell_type": "code",
116 | "execution_count": null,
117 | "metadata": {
118 | "slideshow": {
119 | "slide_type": "subslide"
120 | }
121 | },
122 | "outputs": [],
123 | "source": [
124 | "# vyrobení textového souboru\n",
125 | "with open(\"data/test.txt\", mode=\"w\", encoding=\"utf8\") as f:\n",
126 | " f.write(\"funguje to?\\n\")\n",
127 | " print(\"such print, very newline\", file=f)"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": null,
133 | "metadata": {
134 | "slideshow": {
135 | "slide_type": "subslide"
136 | }
137 | },
138 | "outputs": [],
139 | "source": [
140 | "# přečtení celého souboru najednou\n",
141 | "with open(\"data/test.txt\", mode=\"r\", encoding=\"utf8\") as f:\n",
142 | " print(f.read())"
143 | ]
144 | },
145 | {
146 | "cell_type": "code",
147 | "execution_count": null,
148 | "metadata": {
149 | "slideshow": {
150 | "slide_type": "fragment"
151 | }
152 | },
153 | "outputs": [],
154 | "source": [
155 | "# přečtení po řádcích\n",
156 | "with open(\"data/test.txt\", mode=\"r\", encoding=\"utf8\") as f:\n",
157 | " for radka in f:\n",
158 | " print(radka) # proč dvojí odřádkování?"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": null,
164 | "metadata": {
165 | "slideshow": {
166 | "slide_type": "fragment"
167 | }
168 | },
169 | "outputs": [],
170 | "source": [
171 | "# přečtení *najednou* a rozdělení po řádcích\n",
172 | "radky = []\n",
173 | "with open(\"data/test.txt\", mode=\"r\", encoding=\"utf8\") as f:\n",
174 | " radky = f.readlines()\n",
175 | "print(radky)"
176 | ]
177 | },
178 | {
179 | "cell_type": "markdown",
180 | "metadata": {
181 | "slideshow": {
182 | "slide_type": "subslide"
183 | }
184 | },
185 | "source": [
186 | "### Co je pod kapotou?\n",
187 | "\n",
188 | "[I/O streamy](https://docs.python.org/3/library/io.html#module-io):\n",
189 | "\n",
190 | "- `IOBase(object) – close, __enter__, __exit__, __iter__, __next__` a další\n",
191 | "- `RawIOBase(IOBase) – read, write` a další\n",
192 | "- ... další vrstvy tříd pro bufferování, dekódování apod.\n"
193 | ]
194 | },
195 | {
196 | "cell_type": "markdown",
197 | "metadata": {
198 | "slideshow": {
199 | "slide_type": "slide"
200 | }
201 | },
202 | "source": [
203 | "### `StringIO`\n",
204 | "\n",
205 | "= I/O stream – tedy se chová jako soubor – ale nachází se v paměti."
206 | ]
207 | },
208 | {
209 | "cell_type": "code",
210 | "execution_count": null,
211 | "metadata": {
212 | "slideshow": {
213 | "slide_type": "-"
214 | }
215 | },
216 | "outputs": [],
217 | "source": [
218 | "from io import StringIO\n",
219 | "\n",
220 | "def hloupa_fce(soubor):\n",
221 | " # hloupá funkce pracuje jenom se soubory a nemůžeme to změnit\n",
222 | " soubor.write(\"hloupá data\")\n",
223 | "\n",
224 | "with StringIO() as falesny_soubor:\n",
225 | " hloupa_fce(falesny_soubor)\n",
226 | " print(falesny_soubor.getvalue())"
227 | ]
228 | },
229 | {
230 | "cell_type": "markdown",
231 | "metadata": {
232 | "slideshow": {
233 | "slide_type": "slide"
234 | }
235 | },
236 | "source": [
237 | "## Systémové proudy\n",
238 | "\n",
239 | "- výstupní: `stdout`\n",
240 | "- chybový: `stderr`\n",
241 | "- vstupní: `stdin`"
242 | ]
243 | },
244 | {
245 | "cell_type": "code",
246 | "execution_count": null,
247 | "metadata": {
248 | "slideshow": {
249 | "slide_type": "subslide"
250 | }
251 | },
252 | "outputs": [],
253 | "source": [
254 | "import sys\n",
255 | "\n",
256 | "print(\"standardní výstup\", file=sys.stdout)\n",
257 | "print(\"jejda\", file=sys.stderr)\n",
258 | "\n",
259 | "# umožňuje např. shell: `cat data.txt | python3 zpracuj.py`\n",
260 | "for radka in sys.stdin:\n",
261 | " print(\"přijata řádka:\", radka) # dvojí odřádkování ..."
262 | ]
263 | },
264 | {
265 | "cell_type": "markdown",
266 | "metadata": {
267 | "slideshow": {
268 | "slide_type": "slide"
269 | }
270 | },
271 | "source": [
272 | "## Dej mi vstup!\n",
273 | "\n",
274 | "```python\n",
275 | "import fileinput\n",
276 | "\n",
277 | "# zde selže – interaktivní režim\n",
278 | "for radka in fileinput.input():\n",
279 | " print(radka)\n",
280 | "```\n",
281 | "\n",
282 | "**Použití:**\n",
283 | "\n",
284 | "- `cat data.txt | python3 zpracuj.py`\n",
285 | "- `python3 zpracuj.py data.txt`\n",
286 | "- `python3 zpracuj.py data.txt data2.txt`\n",
287 | "- `python3 zpracuj.py < data.txt`"
288 | ]
289 | },
290 | {
291 | "cell_type": "markdown",
292 | "metadata": {
293 | "slideshow": {
294 | "slide_type": "slide"
295 | }
296 | },
297 | "source": [
298 | "## Dočasné soubory"
299 | ]
300 | },
301 | {
302 | "cell_type": "code",
303 | "execution_count": null,
304 | "metadata": {},
305 | "outputs": [],
306 | "source": [
307 | "from tempfile import TemporaryFile\n",
308 | "\n",
309 | "# pozor, výchozí mód je `w+b` = binární!\n",
310 | "with TemporaryFile(mode=\"w+\", encoding=\"utf8\") as f:\n",
311 | " print(\"dočasný obsah\", file=f)\n",
312 | " \n",
313 | " # kurzor zpět na začátek a přečíst data\n",
314 | " f.seek(0)\n",
315 | " print(f.read())"
316 | ]
317 | },
318 | {
319 | "cell_type": "markdown",
320 | "metadata": {
321 | "slideshow": {
322 | "slide_type": "slide"
323 | }
324 | },
325 | "source": [
326 | "# Cesty a složky\n",
327 | "\n",
328 | "Dříve kombinace modulů [`os.path`](https://docs.python.org/3/library/os.path.html#module-os.path) a [`glob`](https://docs.python.org/3/library/glob.html), dnes většinově nahrazeno objektovým přístupem – [`pathlib`](https://docs.python.org/3/library/pathlib.html).\n",
329 | "\n",
330 | "Modul `pathlib` se chová \"správně\" pro Windows / Posix.\n",
331 | "\n",
332 | "- `PurePath` – operace pouze s cestou.\n",
333 | "- `Path(PurePath)` – fyzicky sahá na disk."
334 | ]
335 | },
336 | {
337 | "cell_type": "code",
338 | "execution_count": null,
339 | "metadata": {
340 | "slideshow": {
341 | "slide_type": "subslide"
342 | }
343 | },
344 | "outputs": [],
345 | "source": [
346 | "from pathlib import Path\n",
347 | "\n",
348 | "# vytvoření objektu cesty\n",
349 | "aktualni = Path(\".\")\n",
350 | "print(repr(aktualni))\n",
351 | "print(aktualni) # používá __str__"
352 | ]
353 | },
354 | {
355 | "cell_type": "code",
356 | "execution_count": null,
357 | "metadata": {
358 | "slideshow": {
359 | "slide_type": "-"
360 | }
361 | },
362 | "outputs": [],
363 | "source": [
364 | "# navigace mezi adresáři (spojování cest)\n",
365 | "nadrazeny = aktualni / \"..\" / Path(\"..\") / \"..\" # používá __div__\n",
366 | "print(nadrazeny)"
367 | ]
368 | },
369 | {
370 | "cell_type": "code",
371 | "execution_count": null,
372 | "metadata": {
373 | "slideshow": {
374 | "slide_type": "-"
375 | }
376 | },
377 | "outputs": [],
378 | "source": [
379 | "# \"absolutizace\" a vyřazení symlinků\n",
380 | "print(nadrazeny.resolve())"
381 | ]
382 | },
383 | {
384 | "cell_type": "code",
385 | "execution_count": null,
386 | "metadata": {
387 | "slideshow": {
388 | "slide_type": "-"
389 | }
390 | },
391 | "outputs": [],
392 | "source": [
393 | "# porovnání (používá __eq__)\n",
394 | "print(Path.home() == nadrazeny) # `home` je absolutní, `nadrazeny` relativní\n",
395 | "print(Path.home() == nadrazeny.resolve()) # obě absolutní"
396 | ]
397 | },
398 | {
399 | "cell_type": "code",
400 | "execution_count": null,
401 | "metadata": {
402 | "slideshow": {
403 | "slide_type": "subslide"
404 | }
405 | },
406 | "outputs": [],
407 | "source": [
408 | "# rozebírání na součástky\n",
409 | "verejny_klic = Path.home() / \".ssh\" / \"id_rsa.pub\"\n",
410 | "print(verejny_klic.parts)\n",
411 | "print(verejny_klic.name)\n",
412 | "print(verejny_klic.stem)\n",
413 | "print(verejny_klic.suffix)"
414 | ]
415 | },
416 | {
417 | "cell_type": "code",
418 | "execution_count": null,
419 | "metadata": {
420 | "slideshow": {
421 | "slide_type": "subslide"
422 | }
423 | },
424 | "outputs": [],
425 | "source": [
426 | "# globbing\n",
427 | "for notebook in Path(\".\").glob(\"**/*.ipynb\"):\n",
428 | " print(notebook.parts)"
429 | ]
430 | },
431 | {
432 | "cell_type": "code",
433 | "execution_count": null,
434 | "metadata": {
435 | "slideshow": {
436 | "slide_type": "subslide"
437 | }
438 | },
439 | "outputs": [],
440 | "source": [
441 | "soubor = Path(\"./data/test.txt\")\n",
442 | "\n",
443 | "# otevírání\n",
444 | "with soubor.open(mode=\"w\", encoding=\"utf8\") as f:\n",
445 | " print(\"Asi brzo umřu..\", file=f)\n",
446 | " \n",
447 | "# mazání\n",
448 | "soubor.unlink()"
449 | ]
450 | },
451 | {
452 | "cell_type": "code",
453 | "execution_count": null,
454 | "metadata": {
455 | "slideshow": {
456 | "slide_type": "subslide"
457 | }
458 | },
459 | "outputs": [],
460 | "source": [
461 | "# spousta dalších možností ...\n",
462 | "dir(Path(\".\"))"
463 | ]
464 | },
465 | {
466 | "cell_type": "markdown",
467 | "metadata": {
468 | "slideshow": {
469 | "slide_type": "slide"
470 | }
471 | },
472 | "source": [
473 | "# Archivace a komprese"
474 | ]
475 | },
476 | {
477 | "cell_type": "code",
478 | "execution_count": null,
479 | "metadata": {
480 | "slideshow": {
481 | "slide_type": "fragment"
482 | }
483 | },
484 | "outputs": [],
485 | "source": [
486 | "import shutil"
487 | ]
488 | },
489 | {
490 | "cell_type": "code",
491 | "execution_count": null,
492 | "metadata": {
493 | "slideshow": {
494 | "slide_type": "subslide"
495 | }
496 | },
497 | "outputs": [],
498 | "source": [
499 | "# zabalení\n",
500 | "shutil.make_archive(\"data/lonely-file\", format=\"zip\", base_dir=\"data/leave-me-alone.txt\")"
501 | ]
502 | },
503 | {
504 | "cell_type": "code",
505 | "execution_count": null,
506 | "metadata": {
507 | "slideshow": {
508 | "slide_type": "fragment"
509 | }
510 | },
511 | "outputs": [],
512 | "source": [
513 | "# rozbalení\n",
514 | "shutil.unpack_archive(\"data/lonely-file.zip\", extract_dir=\"./tmp\")"
515 | ]
516 | },
517 | {
518 | "cell_type": "code",
519 | "execution_count": null,
520 | "metadata": {
521 | "slideshow": {
522 | "slide_type": "skip"
523 | }
524 | },
525 | "outputs": [],
526 | "source": [
527 | "# úklid ...\n",
528 | "Path(\"data/lonely-file.zip\").unlink()\n",
529 | "shutil.rmtree(\"./tmp\")"
530 | ]
531 | },
532 | {
533 | "cell_type": "markdown",
534 | "metadata": {
535 | "slideshow": {
536 | "slide_type": "subslide"
537 | }
538 | },
539 | "source": [
540 | "Moduly [`zipfile`](https://docs.python.org/3/library/zipfile.html) a [`tarfile`](https://docs.python.org/3/library/tarfile.html) poskytují širší možnosti, zejména:\n",
541 | "\n",
542 | "- prohlížení obsahu archivu bez rozbalení\n",
543 | "- přidávání jednotlivých souborů\n",
544 | "\n",
545 | "=> složitější rozhraní"
546 | ]
547 | },
548 | {
549 | "cell_type": "markdown",
550 | "metadata": {
551 | "slideshow": {
552 | "slide_type": "fragment"
553 | }
554 | },
555 | "source": [
556 | "[`tarfile.open()`](https://docs.python.org/3/library/tarfile.html#tarfile.open):\n",
557 | "\n",
558 | "```\n",
559 | "[mód]:[komprese] - \"r:*\", \"w:gz\" apod.\n",
560 | "```"
561 | ]
562 | },
563 | {
564 | "cell_type": "markdown",
565 | "metadata": {
566 | "slideshow": {
567 | "slide_type": "slide"
568 | }
569 | },
570 | "source": [
571 | "## Další možnosti\n",
572 | "\n",
573 | "- [zbytek modulu `shutil`](https://docs.python.org/3/library/shutil.html) – Komplexnější operace jako mazání neprázdných složek nebo kopírování souborů skládající se z více elementárních operací.\n",
574 | "\n",
575 | "- [modul `stat`](https://docs.python.org/3/library/stat.html) – Převážně sada konstant pro práci s oprávněními."
576 | ]
577 | },
578 | {
579 | "cell_type": "markdown",
580 | "metadata": {
581 | "slideshow": {
582 | "slide_type": "slide"
583 | }
584 | },
585 | "source": [
586 | "# Příklad\n",
587 | "Na základě souboru `/etc/passwd` vytvořte soubor `passwd.json`, kam přeneste:\n",
588 | "- username\n",
589 | "- UID\n",
590 | "- common name\n",
591 | "- login shell"
592 | ]
593 | },
594 | {
595 | "cell_type": "code",
596 | "execution_count": null,
597 | "metadata": {},
598 | "outputs": [],
599 | "source": [
600 | "from json import dump\n",
601 | "\n",
602 | "# TODO"
603 | ]
604 | },
605 | {
606 | "cell_type": "markdown",
607 | "metadata": {
608 | "slideshow": {
609 | "slide_type": "slide"
610 | }
611 | },
612 | "source": [
613 | "# Příklad\n",
614 | "\n",
615 | "- Najděte všechny soubory s příponou `.ipynb` v aktuálním adresáři (použijte `pathlib`).\n",
616 | "- Projděte je všechny po řádcích (použijte `for` nebo `fileinput`).\n",
617 | "- Všechny řádky, které obsahují slovo *\"chyba\"* vypište na systémový chybový výstup.\n",
618 | "- Všechny ostatní řádky vypište do souboru `data/software-bez-chyb.txt`.\n",
619 | "- Tento soubor zabalte do archivu `data/software-bez-chyb.tar.gz`."
620 | ]
621 | },
622 | {
623 | "cell_type": "code",
624 | "execution_count": null,
625 | "metadata": {
626 | "slideshow": {
627 | "slide_type": "skip"
628 | }
629 | },
630 | "outputs": [],
631 | "source": [
632 | "import sys\n",
633 | "import fileinput\n",
634 | "import shutil\n",
635 | "from pathlib import Path\n",
636 | "\n",
637 | "# TODO"
638 | ]
639 | }
640 | ],
641 | "metadata": {
642 | "kernelspec": {
643 | "display_name": "Python 3",
644 | "language": "python",
645 | "name": "python3"
646 | },
647 | "language_info": {
648 | "codemirror_mode": {
649 | "name": "ipython",
650 | "version": 3
651 | },
652 | "file_extension": ".py",
653 | "mimetype": "text/x-python",
654 | "name": "python",
655 | "nbconvert_exporter": "python",
656 | "pygments_lexer": "ipython3",
657 | "version": "3.6.4"
658 | }
659 | },
660 | "nbformat": 4,
661 | "nbformat_minor": 1
662 | }
663 |
--------------------------------------------------------------------------------
/05-generatory-iteratory.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# Generátorová notace pro `list`\n",
12 | "\n",
13 | "= Anglicky: \"list comprehension\".\n",
14 | "\n",
15 | "Umožňuje velmi elegantně vytvořit z jedné sekvence jinou. Umí to samé, co funkce `map` a `filter` dohromady."
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": null,
21 | "metadata": {
22 | "collapsed": true,
23 | "slideshow": {
24 | "slide_type": "subslide"
25 | }
26 | },
27 | "outputs": [],
28 | "source": [
29 | "cisla = list(range(20))\n",
30 | "\n",
31 | "# list comprehension\n",
32 | "druhe_mocniny = [cislo ** 2 for cislo in cisla if cislo > 5]"
33 | ]
34 | },
35 | {
36 | "cell_type": "code",
37 | "execution_count": null,
38 | "metadata": {
39 | "collapsed": true,
40 | "slideshow": {
41 | "slide_type": "fragment"
42 | }
43 | },
44 | "outputs": [],
45 | "source": [
46 | "# to samé pomocí for\n",
47 | "druhe_mocniny = []\n",
48 | "for cislo in cisla:\n",
49 | " if cislo > 5:\n",
50 | " druhe_mocniny.append(cislo ** 2)"
51 | ]
52 | },
53 | {
54 | "cell_type": "code",
55 | "execution_count": null,
56 | "metadata": {
57 | "collapsed": false,
58 | "slideshow": {
59 | "slide_type": "fragment"
60 | }
61 | },
62 | "outputs": [],
63 | "source": [
64 | "# to samé pomocí map, filter a lambda funkcí\n",
65 | "druhe_mocniny = list( map(lambda cislo: cislo ** 2, filter(lambda cislo: cislo > 5, cisla)) )"
66 | ]
67 | },
68 | {
69 | "cell_type": "markdown",
70 | "metadata": {
71 | "slideshow": {
72 | "slide_type": "subslide"
73 | }
74 | },
75 | "source": [
76 | "```python\n",
77 | "# syntaxe\n",
78 | "[VYRAZ for PROMENNA in SEKVENCE if PODMINKA]\n",
79 | "```\n",
80 | "\n",
81 | "- `SEKVENCE` + `PROMENNA` = stejně jako hlavička `for`\n",
82 | "- `VYRAZ` = vnitřek volání `append`\n",
83 | "- `PODMINKA` = podmínka uvnitř těla `for`, *volitelná součást*"
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": null,
89 | "metadata": {
90 | "collapsed": false,
91 | "slideshow": {
92 | "slide_type": "subslide"
93 | }
94 | },
95 | "outputs": [],
96 | "source": [
97 | "# lze volat funkce\n",
98 | "[ord(ch) for ch in \"Ahoj svete!\" if ord(\"a\") <= ord(ch) <= ord(\"z\")]"
99 | ]
100 | },
101 | {
102 | "cell_type": "code",
103 | "execution_count": null,
104 | "metadata": {
105 | "collapsed": false,
106 | "slideshow": {
107 | "slide_type": "fragment"
108 | }
109 | },
110 | "outputs": [],
111 | "source": [
112 | "# lze vnořovat - opatrně\n",
113 | "[ [(x, y) for y in range(5)] for x in range(3)]"
114 | ]
115 | },
116 | {
117 | "cell_type": "code",
118 | "execution_count": null,
119 | "metadata": {
120 | "collapsed": false,
121 | "slideshow": {
122 | "slide_type": "fragment"
123 | }
124 | },
125 | "outputs": [],
126 | "source": [
127 | "# jakási varianta kartézského součinu - taky opatrně\n",
128 | "data = [(x, y) for y in range(3) for x in range(2)]\n",
129 | "\n",
130 | "# ekvivalentní zápis\n",
131 | "for y in range(3):\n",
132 | " for x in range(2):\n",
133 | " data.append((x, y))\n",
134 | "print(data)"
135 | ]
136 | },
137 | {
138 | "cell_type": "markdown",
139 | "metadata": {
140 | "slideshow": {
141 | "slide_type": "subslide"
142 | }
143 | },
144 | "source": [
145 | "# Generátorová notace pro `dict`\n",
146 | "\n",
147 | "Vychází z list comprehension.\n",
148 | "\n",
149 | "```python\n",
150 | "# syntaxe\n",
151 | "{KLIC: HODNOTA for PROMENNA in SEKVENCE if PODMINKA}\n",
152 | "```"
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": null,
158 | "metadata": {
159 | "collapsed": false,
160 | "slideshow": {
161 | "slide_type": "subslide"
162 | }
163 | },
164 | "outputs": [],
165 | "source": [
166 | "# slovník mocnin dvou\n",
167 | "{x: 2 ** x for x in range(10)}"
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "execution_count": null,
173 | "metadata": {
174 | "collapsed": false,
175 | "slideshow": {
176 | "slide_type": "fragment"
177 | }
178 | },
179 | "outputs": [],
180 | "source": [
181 | "import math\n",
182 | "\n",
183 | "def slozity_vypocet(vstup):\n",
184 | " return math.sin(vstup)\n",
185 | "\n",
186 | "# sinus sudých čísel v intervalu <0; 10) s textovým klíčem\n",
187 | "{\"hodnota-{}\".format(x): slozity_vypocet(x) for x in range(10) if x % 2 == 0}"
188 | ]
189 | },
190 | {
191 | "cell_type": "markdown",
192 | "metadata": {
193 | "slideshow": {
194 | "slide_type": "subslide"
195 | }
196 | },
197 | "source": [
198 | "# Generátorová notace pro `set`\n"
199 | ]
200 | },
201 | {
202 | "cell_type": "code",
203 | "execution_count": null,
204 | "metadata": {
205 | "collapsed": false
206 | },
207 | "outputs": [],
208 | "source": [
209 | "{pismeno for pismeno in \"hustodémonsky megakrutopřísně\" if ord(pismeno) >= ord(\"o\")}"
210 | ]
211 | },
212 | {
213 | "cell_type": "markdown",
214 | "metadata": {
215 | "slideshow": {
216 | "slide_type": "subslide"
217 | }
218 | },
219 | "source": [
220 | "# Generátorová notace pro generátor"
221 | ]
222 | },
223 | {
224 | "cell_type": "code",
225 | "execution_count": null,
226 | "metadata": {
227 | "collapsed": false,
228 | "slideshow": {
229 | "slide_type": "-"
230 | }
231 | },
232 | "outputs": [],
233 | "source": [
234 | "(cislo ** 2 for cislo in range(10000000) if cislo > 5)"
235 | ]
236 | },
237 | {
238 | "cell_type": "markdown",
239 | "metadata": {
240 | "slideshow": {
241 | "slide_type": "fragment"
242 | }
243 | },
244 | "source": [
245 | ""
246 | ]
247 | },
248 | {
249 | "cell_type": "markdown",
250 | "metadata": {
251 | "slideshow": {
252 | "slide_type": "slide"
253 | }
254 | },
255 | "source": [
256 | "# Generátor\n",
257 | "\n",
258 | "= Věc, která umí generovat sekvenci prvků (konečnou nebo nekonečnou). Nedělá to však najednou, ale drží si *vnitřní stav* a prvky vydává *postupně*, jak jsou potřeba."
259 | ]
260 | },
261 | {
262 | "cell_type": "code",
263 | "execution_count": null,
264 | "metadata": {
265 | "collapsed": false
266 | },
267 | "outputs": [],
268 | "source": [
269 | "# konečný generátor\n",
270 | "def zdravic():\n",
271 | " yield \"ahoj\"\n",
272 | " yield \"nazdar\"\n",
273 | " # automatický raise StopIteration()\n",
274 | " \n",
275 | "for pozdrav in zdravic():\n",
276 | " print(pozdrav)"
277 | ]
278 | },
279 | {
280 | "cell_type": "code",
281 | "execution_count": null,
282 | "metadata": {
283 | "collapsed": false,
284 | "slideshow": {
285 | "slide_type": "subslide"
286 | }
287 | },
288 | "outputs": [],
289 | "source": [
290 | "# nekonečný generátor\n",
291 | "def stamgast():\n",
292 | " print(\"Nazdar hospodskej!\")\n",
293 | " yield \"Chci pivo.\"\n",
294 | " while True:\n",
295 | " yield \"Ještě jedno...\"\n",
296 | "\n",
297 | "for kolik_piv, co_to_bude in enumerate(stamgast()):\n",
298 | " print(co_to_bude)\n",
299 | " if kolik_piv >= 3:\n",
300 | " break"
301 | ]
302 | },
303 | {
304 | "cell_type": "markdown",
305 | "metadata": {
306 | "slideshow": {
307 | "slide_type": "subslide"
308 | }
309 | },
310 | "source": [
311 | "## Co se děje?"
312 | ]
313 | },
314 | {
315 | "cell_type": "code",
316 | "execution_count": null,
317 | "metadata": {
318 | "collapsed": false
319 | },
320 | "outputs": [],
321 | "source": [
322 | "pepa = stamgast() # trochu připomíná konstruktor, že?\n",
323 | "print(\"Nazdar Pepo.\") # pořadí !!\n",
324 | "print(\"1:\", next(pepa))\n",
325 | "print(\"2:\", next(pepa))\n",
326 | "print(\"3:\", next(pepa))"
327 | ]
328 | },
329 | {
330 | "cell_type": "markdown",
331 | "metadata": {
332 | "slideshow": {
333 | "slide_type": "slide"
334 | }
335 | },
336 | "source": [
337 | "# Iterátor\n",
338 | "\n",
339 | "= Generátor v objektovém podání. Používá magické metody:\n",
340 | "\n",
341 | "- `__iter__` – Vytváří iterátor. Vrací objekt, na kterém se má volat `__next__`.\n",
342 | "- `__next__` – Vrací další prvek nebo výjimku `StopIteration`."
343 | ]
344 | },
345 | {
346 | "cell_type": "code",
347 | "execution_count": null,
348 | "metadata": {
349 | "collapsed": false,
350 | "slideshow": {
351 | "slide_type": "subslide"
352 | }
353 | },
354 | "outputs": [],
355 | "source": [
356 | "from random import shuffle\n",
357 | "\n",
358 | "class Posta(object):\n",
359 | " \n",
360 | " def __init__(self):\n",
361 | " self.baliky = [\"velký\", \"malý\", \"rozbitý\", \"politý\", \"ohořelý\"]\n",
362 | " \n",
363 | " # oblíbený trik se `self`\n",
364 | " def __iter__(self):\n",
365 | " shuffle(self.baliky)\n",
366 | " return self\n",
367 | " \n",
368 | " def __next__(self):\n",
369 | " # balíky už nejsou\n",
370 | " if not self.baliky:\n",
371 | " raise StopIteration()\n",
372 | " \n",
373 | " # vydat balík\n",
374 | " return self.baliky.pop()\n",
375 | "\n",
376 | "# zákaznická smyčka\n",
377 | "for balik in Posta():\n",
378 | " print(balik)"
379 | ]
380 | },
381 | {
382 | "cell_type": "markdown",
383 | "metadata": {
384 | "slideshow": {
385 | "slide_type": "slide"
386 | }
387 | },
388 | "source": [
389 | "# Příklad\n",
390 | "\n",
391 | "- Otevřete soubor `data/accel.csv` a přečtěte ho po řádcích, komentáře přeskakujte.\n",
392 | "- Kód obalte do generátoru nebo iterátoru, který řádky generuje po jednom.\n",
393 | "- Vytvořte seznam *časů* vzorků, které mají zrychlení alespoň v jedné ose absolutně větší než 1 (použijte list comprehension a vámi vytvořený generátor / iterátor).\n",
394 | "\n",
395 | "Příklad hledaného vzroku: \n",
396 | "`101.776 -0.01171875 -0.10546875 -1.0078125`"
397 | ]
398 | }
399 | ],
400 | "metadata": {
401 | "kernelspec": {
402 | "display_name": "Python 3",
403 | "language": "python",
404 | "name": "python3"
405 | },
406 | "language_info": {
407 | "codemirror_mode": {
408 | "name": "ipython",
409 | "version": 3
410 | },
411 | "file_extension": ".py",
412 | "mimetype": "text/x-python",
413 | "name": "python",
414 | "nbconvert_exporter": "python",
415 | "pygments_lexer": "ipython3",
416 | "version": "3.5.2"
417 | }
418 | },
419 | "nbformat": 4,
420 | "nbformat_minor": 0
421 | }
422 |
--------------------------------------------------------------------------------
/06-dobre-zvyky.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# [PEP8](https://www.python.org/dev/peps/pep-0008/) – Style Guide for Python Code"
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "metadata": {
17 | "slideshow": {
18 | "slide_type": "subslide"
19 | }
20 | },
21 | "source": [
22 | "## Nejdůležitější v kostce\n",
23 | "\n",
24 | "- odsazení 4 mezery\n",
25 | "- žádné středníky\n",
26 | "- UTF-8\n",
27 | "- anglicky\n",
28 | "- nainstalovat automatický buzerovač (např. [flake8](http://flake8.pycqa.org/en/latest/))"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {
34 | "slideshow": {
35 | "slide_type": "slide"
36 | }
37 | },
38 | "source": [
39 | "## Pojmenování\n",
40 | "\n",
41 | "- `mala_podtrzitka` – proměnné, funkce, atributy, metody\n",
42 | "- `VELKA_PODTRZITKA` – konstanty\n",
43 | "- `PrvniVelkaDohromady` – třídy\n",
44 | "- `_podtrzitko_na_zacatku` – privátní věci"
45 | ]
46 | },
47 | {
48 | "cell_type": "markdown",
49 | "metadata": {
50 | "slideshow": {
51 | "slide_type": "slide"
52 | }
53 | },
54 | "source": [
55 | "## Nejčastější prohřešky"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": 12,
61 | "metadata": {
62 | "collapsed": false,
63 | "slideshow": {
64 | "slide_type": "subslide"
65 | }
66 | },
67 | "outputs": [],
68 | "source": [
69 | "# mezery u operátorů a struktur\n",
70 | "\n",
71 | "# NE\n",
72 | "x=2\n",
73 | "y = (x*2)-4\n",
74 | "slovnik = {\"a\":1,\"b\":3}\n",
75 | "seznam = [12,5,2]\n",
76 | "\n",
77 | "# ANO\n",
78 | "x = 2\n",
79 | "y = (x * 2) - 4\n",
80 | "slovnik = {\"a\": 1, \"b\": 3}\n",
81 | "seznam = [12, 5, 2]"
82 | ]
83 | },
84 | {
85 | "cell_type": "code",
86 | "execution_count": 18,
87 | "metadata": {
88 | "collapsed": true,
89 | "slideshow": {
90 | "slide_type": "subslide"
91 | }
92 | },
93 | "outputs": [],
94 | "source": [
95 | "# mezery v hlavičkách funkcí a volání funkcí\n",
96 | "\n",
97 | "# NE\n",
98 | "def udelej( co,*args,jak = None,**kwargs ):\n",
99 | " return max(1,2,3)\n",
100 | "\n",
101 | "# ANO\n",
102 | "def udelej(co, *args, jak=None, **kwargs):\n",
103 | " return max(1, 2, 3)"
104 | ]
105 | },
106 | {
107 | "cell_type": "code",
108 | "execution_count": 15,
109 | "metadata": {
110 | "collapsed": false,
111 | "slideshow": {
112 | "slide_type": "subslide"
113 | }
114 | },
115 | "outputs": [
116 | {
117 | "name": "stdout",
118 | "output_type": "stream",
119 | "text": [
120 | "jeden druhy\n",
121 | "jeden druhy\n",
122 | "jeden druhy\n",
123 | "jeden druhy\n"
124 | ]
125 | }
126 | ],
127 | "source": [
128 | "# sčítání řetězců\n",
129 | "\n",
130 | "# NE\n",
131 | "print(\"jeden \" + \"druhy\")\n",
132 | "\n",
133 | "# ANO\n",
134 | "print(\" \".join([\"jeden\", \"druhy\"]))\n",
135 | "print(\"{} {}\".format(\"jeden\", \"druhy\"))\n",
136 | "print(\"jeden\", \"druhy\")"
137 | ]
138 | },
139 | {
140 | "cell_type": "code",
141 | "execution_count": 24,
142 | "metadata": {
143 | "collapsed": false,
144 | "slideshow": {
145 | "slide_type": "subslide"
146 | }
147 | },
148 | "outputs": [
149 | {
150 | "data": {
151 | "text/plain": [
152 | "<_io.TextIOWrapper name='data/leave-me-alone.txt' mode='r' encoding='utf8'>"
153 | ]
154 | },
155 | "execution_count": 24,
156 | "metadata": {},
157 | "output_type": "execute_result"
158 | }
159 | ],
160 | "source": [
161 | "# spoléhání na implicitní chování\n",
162 | "\n",
163 | "# NE\n",
164 | "a = 1 + 2 * 3\n",
165 | "ntice = 1, 2, 3\n",
166 | "open(\"data/leave-me-alone.txt\")\n",
167 | "\n",
168 | "# ANO\n",
169 | "a = 1 + (2 * 3)\n",
170 | "ntice = (1, 2, 3)\n",
171 | "open(\"data/leave-me-alone.txt\", mode=\"r\", encoding=\"utf8\")"
172 | ]
173 | },
174 | {
175 | "cell_type": "markdown",
176 | "metadata": {
177 | "slideshow": {
178 | "slide_type": "slide"
179 | }
180 | },
181 | "source": [
182 | "# [PEP20](https://www.python.org/dev/peps/pep-0020/) – The Zen of Python"
183 | ]
184 | },
185 | {
186 | "cell_type": "code",
187 | "execution_count": 1,
188 | "metadata": {
189 | "collapsed": false,
190 | "scrolled": true,
191 | "slideshow": {
192 | "slide_type": "subslide"
193 | }
194 | },
195 | "outputs": [
196 | {
197 | "name": "stdout",
198 | "output_type": "stream",
199 | "text": [
200 | "The Zen of Python, by Tim Peters\n",
201 | "\n",
202 | "Beautiful is better than ugly.\n",
203 | "Explicit is better than implicit.\n",
204 | "Simple is better than complex.\n",
205 | "Complex is better than complicated.\n",
206 | "Flat is better than nested.\n",
207 | "Sparse is better than dense.\n",
208 | "Readability counts.\n",
209 | "Special cases aren't special enough to break the rules.\n",
210 | "Although practicality beats purity.\n",
211 | "Errors should never pass silently.\n",
212 | "Unless explicitly silenced.\n",
213 | "In the face of ambiguity, refuse the temptation to guess.\n",
214 | "There should be one-- and preferably only one --obvious way to do it.\n",
215 | "Although that way may not be obvious at first unless you're Dutch.\n",
216 | "Now is better than never.\n",
217 | "Although never is often better than *right* now.\n",
218 | "If the implementation is hard to explain, it's a bad idea.\n",
219 | "If the implementation is easy to explain, it may be a good idea.\n",
220 | "Namespaces are one honking great idea -- let's do more of those!\n"
221 | ]
222 | }
223 | ],
224 | "source": [
225 | "import this"
226 | ]
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "metadata": {
231 | "slideshow": {
232 | "slide_type": "subslide"
233 | }
234 | },
235 | "source": [
236 | "### Subjektivní svatá trojice\n",
237 | "\n",
238 | "- Beautiful is better than ugly.\n",
239 | "- Explicit is better than implicit.\n",
240 | "- There should be one-- and preferably only one --obvious way to do it."
241 | ]
242 | },
243 | {
244 | "cell_type": "markdown",
245 | "metadata": {
246 | "slideshow": {
247 | "slide_type": "slide"
248 | }
249 | },
250 | "source": [
251 | "# Idiomy"
252 | ]
253 | },
254 | {
255 | "cell_type": "code",
256 | "execution_count": 28,
257 | "metadata": {
258 | "collapsed": false,
259 | "slideshow": {
260 | "slide_type": "subslide"
261 | }
262 | },
263 | "outputs": [
264 | {
265 | "name": "stdout",
266 | "output_type": "stream",
267 | "text": [
268 | "12\n",
269 | "8\n",
270 | "9\n",
271 | "12\n",
272 | "8\n",
273 | "9\n",
274 | "0 12\n",
275 | "1 8\n",
276 | "2 9\n"
277 | ]
278 | }
279 | ],
280 | "source": [
281 | "data = [12, 8, 9]\n",
282 | "\n",
283 | "# počítadlo v cyklu\n",
284 | "\n",
285 | "# NE\n",
286 | "for i in range(len(data)):\n",
287 | " print(data[i])\n",
288 | " \n",
289 | "# ANO\n",
290 | "for cislo in data:\n",
291 | " print(cislo)\n",
292 | "\n",
293 | "# pokud potřebuju počítadlo\n",
294 | "for i, cislo in enumerate(data):\n",
295 | " print(i, cislo)"
296 | ]
297 | },
298 | {
299 | "cell_type": "code",
300 | "execution_count": 38,
301 | "metadata": {
302 | "collapsed": false,
303 | "slideshow": {
304 | "slide_type": "subslide"
305 | }
306 | },
307 | "outputs": [],
308 | "source": [
309 | "# přiřazení více hodnot najednou\n",
310 | "a, b = 1, 2\n",
311 | "\n",
312 | "# prohození proměnných\n",
313 | "a, b = b, a\n",
314 | "\n",
315 | "# rozbalení zbylých hodnot\n",
316 | "a, b, *zbytek = data\n",
317 | "\n",
318 | "# odpadní proměnná\n",
319 | "a, b, *_ = data"
320 | ]
321 | },
322 | {
323 | "cell_type": "code",
324 | "execution_count": 47,
325 | "metadata": {
326 | "collapsed": false,
327 | "slideshow": {
328 | "slide_type": "subslide"
329 | }
330 | },
331 | "outputs": [
332 | {
333 | "data": {
334 | "text/plain": [
335 | "True"
336 | ]
337 | },
338 | "execution_count": 47,
339 | "metadata": {},
340 | "output_type": "execute_result"
341 | }
342 | ],
343 | "source": [
344 | "# vícero porovnání\n",
345 | "4 < a < 10\n",
346 | "\n",
347 | "# celočíselné dělení\n",
348 | "10 // 3\n",
349 | "\n",
350 | "# operátor is + operátor not\n",
351 | "type(a) is not float\n",
352 | "\n",
353 | "# operátor in\n",
354 | "a in [1, 2, 5]\n",
355 | "\"klic2\" in {\"klic1\": 4, \"klic2\": 5}"
356 | ]
357 | },
358 | {
359 | "cell_type": "markdown",
360 | "metadata": {
361 | "slideshow": {
362 | "slide_type": "slide"
363 | }
364 | },
365 | "source": [
366 | "# Myšlenkové přístupy"
367 | ]
368 | },
369 | {
370 | "cell_type": "markdown",
371 | "metadata": {
372 | "slideshow": {
373 | "slide_type": "subslide"
374 | }
375 | },
376 | "source": [
377 | "## EAFP\n",
378 | "\n",
379 | "> Easier to ask for forgiveness than permission."
380 | ]
381 | },
382 | {
383 | "cell_type": "code",
384 | "execution_count": 58,
385 | "metadata": {
386 | "collapsed": false,
387 | "slideshow": {
388 | "slide_type": "subslide"
389 | }
390 | },
391 | "outputs": [
392 | {
393 | "name": "stdout",
394 | "output_type": "stream",
395 | "text": [
396 | "Zadejte slova oddělená čárkou:a,b\n",
397 | "Zadejte slova oddělená čárkou:a,b\n"
398 | ]
399 | }
400 | ],
401 | "source": [
402 | "# NE\n",
403 | "vstup = input(\"Zadejte slova oddělená čárkou:\")\n",
404 | "if \",\" not in vstup:\n",
405 | " print(\"Špatné zadání.\")\n",
406 | "else:\n",
407 | " druhe_slovo = vstup.split(\",\")[1]\n",
408 | "\n",
409 | "\n",
410 | "# ANO - prostě to zkusit\n",
411 | "try:\n",
412 | " druhe_slovo = input(\"Zadejte slova oddělená čárkou:\").split(\",\")[1]\n",
413 | "except IndexError:\n",
414 | " print(\"Špatné zadání\")"
415 | ]
416 | },
417 | {
418 | "cell_type": "markdown",
419 | "metadata": {
420 | "slideshow": {
421 | "slide_type": "subslide"
422 | }
423 | },
424 | "source": [
425 | "## Duck typing\n",
426 | "\n",
427 | "> If it looks like a duck and quacks like a duck, it must be a duck."
428 | ]
429 | },
430 | {
431 | "cell_type": "code",
432 | "execution_count": 55,
433 | "metadata": {
434 | "collapsed": true,
435 | "slideshow": {
436 | "slide_type": "subslide"
437 | }
438 | },
439 | "outputs": [],
440 | "source": [
441 | "# správně\n",
442 | "def vrat_prvni_prvek(data):\n",
443 | " return data[0]"
444 | ]
445 | },
446 | {
447 | "cell_type": "markdown",
448 | "metadata": {
449 | "slideshow": {
450 | "slide_type": "slide"
451 | }
452 | },
453 | "source": [
454 | "# Úkol\n",
455 | "\n",
456 | "- Nainstalujte a vyzkoušejte si nástroj pro automatickou kontrolu PEP8, např. zmiňovaný [flake8](http://flake8.pycqa.org/en/latest/).\n",
457 | "- Podívejte se na [PEP257](https://www.python.org/dev/peps/pep-0257/)."
458 | ]
459 | }
460 | ],
461 | "metadata": {
462 | "kernelspec": {
463 | "display_name": "Python 3",
464 | "language": "python",
465 | "name": "python3"
466 | },
467 | "language_info": {
468 | "codemirror_mode": {
469 | "name": "ipython",
470 | "version": 3
471 | },
472 | "file_extension": ".py",
473 | "mimetype": "text/x-python",
474 | "name": "python",
475 | "nbconvert_exporter": "python",
476 | "pygments_lexer": "ipython3",
477 | "version": "3.5.2"
478 | }
479 | },
480 | "nbformat": 4,
481 | "nbformat_minor": 0
482 | }
483 |
--------------------------------------------------------------------------------
/07-retezce.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# Objekt `str`"
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {
18 | "collapsed": false,
19 | "slideshow": {
20 | "slide_type": "fragment"
21 | }
22 | },
23 | "outputs": [],
24 | "source": [
25 | "# několik variant, automaticky UTF-8\n",
26 | "\"ahoj\" == \"\"\"ahoj\"\"\" == 'ahoj' == str(\"ahoj\")"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {
32 | "slideshow": {
33 | "slide_type": "subslide"
34 | }
35 | },
36 | "source": [
37 | "## Escape sekvence\n",
38 | "\n",
39 | "- `\\\\` – Zpětné lomítko (\\\\)\n",
40 | "- `\\'` – Jednoduché uvozovky (apostrof) (')\n",
41 | "- `\\\"` – Dvojité (anglické) uvozovky (\")\n",
42 | "- `\\n` – ASCII Linefeed (LF)\n",
43 | "- `\\r` – ASCII Carriage Return (CR)\n",
44 | "- `\\t` – Tabulátor (TAB)"
45 | ]
46 | },
47 | {
48 | "cell_type": "markdown",
49 | "metadata": {
50 | "slideshow": {
51 | "slide_type": "subslide"
52 | }
53 | },
54 | "source": [
55 | "## Raw řetězce\n",
56 | "\n",
57 | "= Ignorují speciální význam zpětných lomítek."
58 | ]
59 | },
60 | {
61 | "cell_type": "code",
62 | "execution_count": null,
63 | "metadata": {
64 | "collapsed": false
65 | },
66 | "outputs": [],
67 | "source": [
68 | "print(r\"bez \\nového řádku\")"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {
74 | "slideshow": {
75 | "slide_type": "subslide"
76 | }
77 | },
78 | "source": [
79 | "## `Bytes`\n",
80 | "\n",
81 | "= Řetězce pouze z ASCII znaků. Chová se jako seznam čísel."
82 | ]
83 | },
84 | {
85 | "cell_type": "code",
86 | "execution_count": null,
87 | "metadata": {
88 | "collapsed": false
89 | },
90 | "outputs": [],
91 | "source": [
92 | "at_command = b\"AT+CSQ\"\n",
93 | "for i in at_command:\n",
94 | " print(i)"
95 | ]
96 | },
97 | {
98 | "cell_type": "markdown",
99 | "metadata": {
100 | "slideshow": {
101 | "slide_type": "subslide"
102 | }
103 | },
104 | "source": [
105 | "## Triky s běžnými metodami"
106 | ]
107 | },
108 | {
109 | "cell_type": "code",
110 | "execution_count": null,
111 | "metadata": {
112 | "collapsed": false,
113 | "slideshow": {
114 | "slide_type": "subslide"
115 | }
116 | },
117 | "outputs": [],
118 | "source": [
119 | "# centrování na šířku konzole (v interaktivním módu nefunguje)\n",
120 | "import os\n",
121 | "width = os.get_terminal_size()[0]\n",
122 | "\"text\".center(width)"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "execution_count": null,
128 | "metadata": {
129 | "collapsed": false,
130 | "slideshow": {
131 | "slide_type": "fragment"
132 | }
133 | },
134 | "outputs": [],
135 | "source": [
136 | "# spojení řetězců s oddělovačem (může být i mezera nebo prázdný)\n",
137 | "\", \".join([\"čaj\", \"rum\", \"bum\"])"
138 | ]
139 | },
140 | {
141 | "cell_type": "code",
142 | "execution_count": null,
143 | "metadata": {
144 | "collapsed": false,
145 | "slideshow": {
146 | "slide_type": "subslide"
147 | }
148 | },
149 | "outputs": [],
150 | "source": [
151 | "# rozdělení a ořezání řádku\n",
152 | "radek = \"max_velikost = 3MB \"\n",
153 | "print( [i.strip() for i in radek.split(\"=\")] )\n",
154 | "\n",
155 | "radek = \"sloupecky oddelene alespon_jednou_mezerou\"\n",
156 | "print( radek.split() )"
157 | ]
158 | },
159 | {
160 | "cell_type": "code",
161 | "execution_count": null,
162 | "metadata": {
163 | "collapsed": false,
164 | "slideshow": {
165 | "slide_type": "fragment"
166 | }
167 | },
168 | "outputs": [],
169 | "source": [
170 | "# násobení stringů - vizuální oddělovač\n",
171 | "\"~\" * 80"
172 | ]
173 | },
174 | {
175 | "cell_type": "markdown",
176 | "metadata": {
177 | "slideshow": {
178 | "slide_type": "subslide"
179 | }
180 | },
181 | "source": [
182 | "- `count`\n",
183 | "- `startswith + endswith`\n",
184 | "- `lower + upper`\n",
185 | "- `replace`\n",
186 | "\n",
187 | "Kompletní seznam metod – [viz dokumentace](https://docs.python.org/3/library/stdtypes.html#string-methods)."
188 | ]
189 | },
190 | {
191 | "cell_type": "markdown",
192 | "metadata": {
193 | "slideshow": {
194 | "slide_type": "subslide"
195 | }
196 | },
197 | "source": [
198 | "## Formátování"
199 | ]
200 | },
201 | {
202 | "cell_type": "code",
203 | "execution_count": null,
204 | "metadata": {
205 | "collapsed": false
206 | },
207 | "outputs": [],
208 | "source": [
209 | "co = \"skládání\"\n",
210 | "\"{} řetězců pomocí {} format\".format(co, \"metody\")"
211 | ]
212 | },
213 | {
214 | "cell_type": "code",
215 | "execution_count": null,
216 | "metadata": {
217 | "collapsed": false,
218 | "slideshow": {
219 | "slide_type": "subslide"
220 | }
221 | },
222 | "outputs": [],
223 | "source": [
224 | "# argumenty lze opakovat\n",
225 | "\"{0} {1} stříkaček stříkalo přes {0} {1} střech\".format(\"tři sta třicet tři\", \"stříbrných\")"
226 | ]
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": null,
231 | "metadata": {
232 | "collapsed": false,
233 | "slideshow": {
234 | "slide_type": "fragment"
235 | }
236 | },
237 | "outputs": [],
238 | "source": [
239 | "# argumenty lze pojmenovat\n",
240 | "\"{jmeno} si dal {jidlo}\".format(jmeno=\"Franta\", jidlo=\"guláš\")"
241 | ]
242 | },
243 | {
244 | "cell_type": "markdown",
245 | "metadata": {
246 | "slideshow": {
247 | "slide_type": "subslide"
248 | }
249 | },
250 | "source": [
251 | "S [format specification mini-language](https://docs.python.org/3/library/string.html#format-specification-mini-language) lze dělat spoustu zajímavých triků.\n",
252 | "\n",
253 | "```\n",
254 | "\"{[argument][:specs]}\".format(...)\n",
255 | "\n",
256 | "[[fill]align][sign][#][0][width][,][.precision][type]\n",
257 | "```"
258 | ]
259 | },
260 | {
261 | "cell_type": "code",
262 | "execution_count": null,
263 | "metadata": {
264 | "collapsed": false,
265 | "slideshow": {
266 | "slide_type": "fragment"
267 | }
268 | },
269 | "outputs": [],
270 | "source": [
271 | "# určení šířky textu\n",
272 | "\"{:20}\".format(\"ahoj\")"
273 | ]
274 | },
275 | {
276 | "cell_type": "code",
277 | "execution_count": null,
278 | "metadata": {
279 | "collapsed": false,
280 | "slideshow": {
281 | "slide_type": "fragment"
282 | }
283 | },
284 | "outputs": [],
285 | "source": [
286 | "# zarovnání v dané šířce\n",
287 | "\"{:>20}\".format(\"ahoj\")"
288 | ]
289 | },
290 | {
291 | "cell_type": "code",
292 | "execution_count": null,
293 | "metadata": {
294 | "collapsed": false,
295 | "slideshow": {
296 | "slide_type": "subslide"
297 | }
298 | },
299 | "outputs": [],
300 | "source": [
301 | "# zarovnání čísel se znaménkem\n",
302 | "print(\"{: >5}\".format(+10))\n",
303 | "print(\"{: >5}\".format(-10))"
304 | ]
305 | },
306 | {
307 | "cell_type": "code",
308 | "execution_count": null,
309 | "metadata": {
310 | "collapsed": false,
311 | "slideshow": {
312 | "slide_type": "fragment"
313 | }
314 | },
315 | "outputs": [],
316 | "source": [
317 | "# konverze\n",
318 | "\"{:e}\".format(6378)"
319 | ]
320 | },
321 | {
322 | "cell_type": "code",
323 | "execution_count": null,
324 | "metadata": {
325 | "collapsed": false,
326 | "slideshow": {
327 | "slide_type": "fragment"
328 | }
329 | },
330 | "outputs": [],
331 | "source": [
332 | "# oddělovač tisíců\n",
333 | "import locale\n",
334 | "locale.setlocale(locale.LC_ALL, \"cs_CZ.UTF-8\") # může se lišit v závislosti na systému\n",
335 | "\"{:n}\".format(1234567890)"
336 | ]
337 | },
338 | {
339 | "cell_type": "code",
340 | "execution_count": null,
341 | "metadata": {
342 | "collapsed": false,
343 | "slideshow": {
344 | "slide_type": "fragment"
345 | }
346 | },
347 | "outputs": [],
348 | "source": [
349 | "# určení desetinné přesnosti + konverze\n",
350 | "import math\n",
351 | "\"{:.4f}\".format(math.pi)"
352 | ]
353 | },
354 | {
355 | "cell_type": "markdown",
356 | "metadata": {
357 | "slideshow": {
358 | "slide_type": "subslide"
359 | }
360 | },
361 | "source": [
362 | "## Modul `string`\n",
363 | "\n",
364 | "Obsahuje několik užitečných konstant:\n",
365 | "\n",
366 | "```\n",
367 | "ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'\n",
368 | "ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n",
369 | "ascii_letters = ascii_lowercase + ascii_uppercase\n",
370 | "digits = '0123456789'\n",
371 | "```"
372 | ]
373 | },
374 | {
375 | "cell_type": "markdown",
376 | "metadata": {
377 | "slideshow": {
378 | "slide_type": "slide"
379 | }
380 | },
381 | "source": [
382 | "# Regulární výrazy"
383 | ]
384 | },
385 | {
386 | "cell_type": "markdown",
387 | "metadata": {
388 | "slideshow": {
389 | "slide_type": "subslide"
390 | }
391 | },
392 | "source": [
393 | "```\n",
394 | "(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]\n",
395 | ")+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\n",
396 | "\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(\n",
397 | "?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \n",
398 | "\\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\0\n",
399 | "31]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\\n",
400 | "](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+\n",
401 | "(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:\n",
402 | "(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z\n",
403 | "|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)\n",
404 | "?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\\n",
405 | "r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[\n",
406 | " \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)\n",
407 | "?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t]\n",
408 | ")*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[\n",
409 | " \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*\n",
410 | ")(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]\n",
411 | ")+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)\n",
412 | "*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+\n",
413 | "|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\n",
414 | "\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\n",
415 | "\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t\n",
416 | "]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031\n",
417 | "]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](\n",
418 | "?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?\n",
419 | ":(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?\n",
420 | ":\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?\n",
421 | ":(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?\n",
422 | "[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*:(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\\\".\\[\\] \n",
423 | "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\n",
424 | "\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>\n",
425 | "@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"\n",
426 | "(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t]\n",
427 | ")*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\n",
428 | "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?\n",
429 | ":[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\n",
430 | "\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\n",
431 | "\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(\n",
432 | "?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;\n",
433 | ":\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([\n",
434 | "^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\"\n",
435 | ".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\\n",
436 | "]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\\n",
437 | "[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\\n",
438 | "r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \n",
439 | "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]\n",
440 | "|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\\\".\\[\\] \\0\n",
441 | "00-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\\n",
442 | ".|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,\n",
443 | ";:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?\n",
444 | ":[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*\n",
445 | "(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\n",
446 | "\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[\n",
447 | "^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]\n",
448 | "]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)(?:,\\s*(\n",
449 | "?:(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\n",
450 | "\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(\n",
451 | "?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\n",
452 | "\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t\n",
453 | "])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t\n",
454 | "])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?\n",
455 | ":\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\n",
456 | "\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:\n",
457 | "[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\\n",
458 | "]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)\n",
459 | "?[ \\t])*(?:@(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"\n",
460 | "()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)\n",
461 | "?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>\n",
462 | "@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[\n",
463 | " \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,\n",
464 | ";:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t]\n",
465 | ")*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\n",
466 | "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?\n",
467 | "(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\n",
468 | "\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\n",
469 | "\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\n",
470 | "\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])\n",
471 | "*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])\n",
472 | "+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\\n",
473 | ".(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z\n",
474 | "|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(\n",
475 | "?:\\r\\n)?[ \\t])*))*)?;\\s*)\n",
476 | "```"
477 | ]
478 | },
479 | {
480 | "cell_type": "markdown",
481 | "metadata": {
482 | "collapsed": true,
483 | "slideshow": {
484 | "slide_type": "subslide"
485 | }
486 | },
487 | "source": [
488 | "Trochu mimo rozsah kurzu... Existují [kvalitní české zdroje](http://www.regularnivyrazy.info/regularni-vyrazy-zaklady.html) a [online vizualizační nástroje](https://www.debuggex.com/)."
489 | ]
490 | },
491 | {
492 | "cell_type": "markdown",
493 | "metadata": {
494 | "collapsed": true,
495 | "slideshow": {
496 | "slide_type": "subslide"
497 | }
498 | },
499 | "source": [
500 | "## V Pythonu"
501 | ]
502 | },
503 | {
504 | "cell_type": "code",
505 | "execution_count": null,
506 | "metadata": {
507 | "collapsed": true
508 | },
509 | "outputs": [],
510 | "source": [
511 | "import re\n",
512 | "mail_regexp = r\"[.\\w]+@[.\\w]+\"\n",
513 | "html_regexp = r\"?\\w+>\"\n",
514 | "text = \"Moje adresa je ja@tbedrich.cz, do školy pak bedritom@fit.cvut.cz.\""
515 | ]
516 | },
517 | {
518 | "cell_type": "code",
519 | "execution_count": null,
520 | "metadata": {
521 | "collapsed": false,
522 | "slideshow": {
523 | "slide_type": "subslide"
524 | }
525 | },
526 | "outputs": [],
527 | "source": [
528 | "# vyhovuje řetězec regexpu?\n",
529 | "re.match(mail_regexp, \"ja@tbedrich.cz\") != None"
530 | ]
531 | },
532 | {
533 | "cell_type": "code",
534 | "execution_count": null,
535 | "metadata": {
536 | "collapsed": false,
537 | "slideshow": {
538 | "slide_type": "fragment"
539 | }
540 | },
541 | "outputs": [],
542 | "source": [
543 | "# všechny výskyty\n",
544 | "for match in re.finditer(mail_regexp, text):\n",
545 | " print(match.group())"
546 | ]
547 | },
548 | {
549 | "cell_type": "code",
550 | "execution_count": null,
551 | "metadata": {
552 | "collapsed": false,
553 | "slideshow": {
554 | "slide_type": "fragment"
555 | }
556 | },
557 | "outputs": [],
558 | "source": [
559 | "# všechny překrývající se výskyty\n",
560 | "re.findall(mail_regexp, text)"
561 | ]
562 | },
563 | {
564 | "cell_type": "code",
565 | "execution_count": null,
566 | "metadata": {
567 | "collapsed": false,
568 | "slideshow": {
569 | "slide_type": "fragment"
570 | }
571 | },
572 | "outputs": [],
573 | "source": [
574 | "# rozřezání textu podle regexpu\n",
575 | "re.split(html_regexp, text)"
576 | ]
577 | },
578 | {
579 | "cell_type": "code",
580 | "execution_count": null,
581 | "metadata": {
582 | "collapsed": false,
583 | "slideshow": {
584 | "slide_type": "fragment"
585 | }
586 | },
587 | "outputs": [],
588 | "source": [
589 | "# nahrazení textu\n",
590 | "re.sub(html_regexp, \"---\", text)"
591 | ]
592 | },
593 | {
594 | "cell_type": "code",
595 | "execution_count": null,
596 | "metadata": {
597 | "collapsed": false,
598 | "slideshow": {
599 | "slide_type": "subslide"
600 | }
601 | },
602 | "outputs": [],
603 | "source": [
604 | "# kompilace regexpu\n",
605 | "mail_pattern = re.compile(mail_regexp, re.IGNORECASE | re.MULTILINE)\n",
606 | "mail_pattern.match(\"smůla\") # změna volání funkcí na metody"
607 | ]
608 | },
609 | {
610 | "cell_type": "code",
611 | "execution_count": null,
612 | "metadata": {
613 | "collapsed": false,
614 | "slideshow": {
615 | "slide_type": "fragment"
616 | }
617 | },
618 | "outputs": [],
619 | "source": [
620 | "# vylepšení regexpu o skupiny\n",
621 | "mail_pattern = re.compile(r\"([.\\w]+)@([.\\w]+)\")"
622 | ]
623 | },
624 | {
625 | "cell_type": "code",
626 | "execution_count": null,
627 | "metadata": {
628 | "collapsed": false,
629 | "slideshow": {
630 | "slide_type": "fragment"
631 | }
632 | },
633 | "outputs": [],
634 | "source": [
635 | "# `findall` začne vracet n-tice skupin\n",
636 | "mail_pattern.findall(text)"
637 | ]
638 | },
639 | {
640 | "cell_type": "code",
641 | "execution_count": null,
642 | "metadata": {
643 | "collapsed": false,
644 | "slideshow": {
645 | "slide_type": "fragment"
646 | }
647 | },
648 | "outputs": [],
649 | "source": [
650 | "# `finditer` vrací \"Match object\", ten má mj. metodu groups()\n",
651 | "for match_obj in mail_pattern.finditer(text):\n",
652 | " print(match_obj.groups())"
653 | ]
654 | },
655 | {
656 | "cell_type": "markdown",
657 | "metadata": {
658 | "slideshow": {
659 | "slide_type": "slide"
660 | }
661 | },
662 | "source": [
663 | "# Příklad\n",
664 | "\n",
665 | "- Otevřete soubor `data/accel.csv` a přečtěte z něj 100 řádků, komentáře přeskočte.\n",
666 | "- Řádky zpracujte a vypište do sloupečků pěkně pod sebe, na 3 desetinná místa (použijte `format`).\n",
667 | "- Upravte výpis tak, aby se hodnoty střídaly na jednom řádku s pauzou 0.1 vteřiny (použijte modul `time` a escape sekvenci `\\r`)."
668 | ]
669 | },
670 | {
671 | "cell_type": "code",
672 | "execution_count": null,
673 | "metadata": {
674 | "collapsed": false,
675 | "slideshow": {
676 | "slide_type": "skip"
677 | }
678 | },
679 | "outputs": [],
680 | "source": [
681 | "from time import sleep\n",
682 | "\n",
683 | "def zpracuj_radek(radek):\n",
684 | " ... # TODO\n",
685 | "\n",
686 | "# TODO otevřít a přečíst soubor"
687 | ]
688 | }
689 | ],
690 | "metadata": {
691 | "kernelspec": {
692 | "display_name": "Python 3",
693 | "language": "python",
694 | "name": "python3"
695 | },
696 | "language_info": {
697 | "codemirror_mode": {
698 | "name": "ipython",
699 | "version": 3
700 | },
701 | "file_extension": ".py",
702 | "mimetype": "text/x-python",
703 | "name": "python",
704 | "nbconvert_exporter": "python",
705 | "pygments_lexer": "ipython3",
706 | "version": "3.5.2"
707 | }
708 | },
709 | "nbformat": 4,
710 | "nbformat_minor": 0
711 | }
712 |
--------------------------------------------------------------------------------
/08-formaty-souboru.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# CSV\n",
12 | "\n",
13 | "= Comma Separated Value"
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {
20 | "collapsed": true,
21 | "slideshow": {
22 | "slide_type": "subslide"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "import csv\n",
28 | "from pprint import pprint"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {
35 | "collapsed": false,
36 | "slideshow": {
37 | "slide_type": "fragment"
38 | }
39 | },
40 | "outputs": [],
41 | "source": [
42 | "# načtení dat\n",
43 | "with open(\"data/menu.csv\", mode=\"r\", encoding=\"utf-8\") as f:\n",
44 | " for radka in csv.reader(f): # delimiter\n",
45 | " print(radka)"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": null,
51 | "metadata": {
52 | "collapsed": false,
53 | "slideshow": {
54 | "slide_type": "subslide"
55 | }
56 | },
57 | "outputs": [],
58 | "source": [
59 | "# načtení do slovníku\n",
60 | "with open(\"data/menu.csv\", mode=\"r\", encoding=\"utf-8\") as f:\n",
61 | " for radka in csv.DictReader(f): # fieldnames\n",
62 | " pprint(radka)"
63 | ]
64 | },
65 | {
66 | "cell_type": "code",
67 | "execution_count": null,
68 | "metadata": {
69 | "collapsed": false,
70 | "slideshow": {
71 | "slide_type": "subslide"
72 | }
73 | },
74 | "outputs": [],
75 | "source": [
76 | "# list\n",
77 | "data = [\n",
78 | " [234, 12, 425],\n",
79 | " [212, 553, 34],\n",
80 | " [\"zrada, \", \"text\", \"s carkou\"],\n",
81 | "]\n",
82 | "\n",
83 | "# generátor\n",
84 | "dalsi_data = (\n",
85 | " (x ** 2 for x in range(y, y + 3))\n",
86 | " for y in range(5)\n",
87 | ")\n",
88 | "\n",
89 | "# zápis\n",
90 | "with open(\"data/write.csv\", mode=\"w\", encoding=\"utf-8\") as f:\n",
91 | " writer = csv.writer(f)\n",
92 | " writer.writerows(data)\n",
93 | " writer.writerows(dalsi_data)"
94 | ]
95 | },
96 | {
97 | "cell_type": "markdown",
98 | "metadata": {
99 | "slideshow": {
100 | "slide_type": "slide"
101 | }
102 | },
103 | "source": [
104 | "# JSON\n",
105 | "\n",
106 | "= JavaScript Object Notation"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "metadata": {
113 | "collapsed": true,
114 | "slideshow": {
115 | "slide_type": "subslide"
116 | }
117 | },
118 | "outputs": [],
119 | "source": [
120 | "import json"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": null,
126 | "metadata": {
127 | "collapsed": false,
128 | "slideshow": {
129 | "slide_type": "fragment"
130 | }
131 | },
132 | "outputs": [],
133 | "source": [
134 | "# čtení\n",
135 | "with open(\"data/widget.json\", mode=\"r\", encoding=\"utf-8\") as f:\n",
136 | " data = json.load(f)\n",
137 | " \n",
138 | "print(type(data))\n",
139 | "pprint(data)"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": null,
145 | "metadata": {
146 | "collapsed": false,
147 | "slideshow": {
148 | "slide_type": "subslide"
149 | }
150 | },
151 | "outputs": [],
152 | "source": [
153 | "# aktualizace\n",
154 | "data[\"widget\"][\"debug\"] = \"off\"\n",
155 | "data[\"widget\"][\"window\"] = {\n",
156 | " \"height\": 640,\n",
157 | " \"width\": 480,\n",
158 | " \"name\": None,\n",
159 | " \"title\": \"Ahoj!\",\n",
160 | "}"
161 | ]
162 | },
163 | {
164 | "cell_type": "code",
165 | "execution_count": null,
166 | "metadata": {
167 | "collapsed": false,
168 | "slideshow": {
169 | "slide_type": "fragment"
170 | }
171 | },
172 | "outputs": [],
173 | "source": [
174 | "# zápis\n",
175 | "with open(\"data/widget_write.json\", mode=\"w\", encoding=\"utf-8\") as f:\n",
176 | " json.dump(data, f, indent=2)"
177 | ]
178 | },
179 | {
180 | "cell_type": "code",
181 | "execution_count": null,
182 | "metadata": {
183 | "collapsed": false,
184 | "slideshow": {
185 | "slide_type": "subslide"
186 | }
187 | },
188 | "outputs": [],
189 | "source": [
190 | "# manipulace s řetězci\n",
191 | "json.loads(\"{}\")\n",
192 | "json.dumps(dict())"
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "execution_count": null,
198 | "metadata": {
199 | "collapsed": false,
200 | "slideshow": {
201 | "slide_type": "fragment"
202 | }
203 | },
204 | "outputs": [],
205 | "source": [
206 | "# chyby\n",
207 | "try:\n",
208 | " json.loads(\"{\")\n",
209 | "except json.JSONDecodeError:\n",
210 | " print(\"Nevalidní JSON.\")"
211 | ]
212 | },
213 | {
214 | "cell_type": "markdown",
215 | "metadata": {
216 | "slideshow": {
217 | "slide_type": "subslide"
218 | }
219 | },
220 | "source": [
221 | "Trik - formátování JSON souboru v konzoli:\n",
222 | "\n",
223 | "```bash\n",
224 | "cat data/widget.json | python -m json.tool\n",
225 | "```"
226 | ]
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "metadata": {
231 | "slideshow": {
232 | "slide_type": "slide"
233 | }
234 | },
235 | "source": [
236 | "# XML\n",
237 | "\n",
238 | "= Extensible Markup Language"
239 | ]
240 | },
241 | {
242 | "cell_type": "markdown",
243 | "metadata": {
244 | "slideshow": {
245 | "slide_type": "fragment"
246 | }
247 | },
248 | "source": [
249 | "~~Tři~~ Dva základní přístupy:\n",
250 | "\n",
251 | "- ElementTree - [`xml.etree.ElementTree`](https://docs.python.org/3/library/xml.etree.elementtree.html).\n",
252 | "- ~~DOM - [`xml.dom`](https://docs.python.org/3/library/xml.dom.html) a [`xml.dom.minidom`](https://docs.python.org/3/library/xml.dom.minidom.html).~~\n",
253 | "- SAX - [`xml.sax`](https://docs.python.org/3/library/xml.sax.html) a [`xml.sax.handler`](https://docs.python.org/3/library/xml.sax.handler.html)"
254 | ]
255 | },
256 | {
257 | "cell_type": "markdown",
258 | "metadata": {
259 | "slideshow": {
260 | "slide_type": "subslide"
261 | }
262 | },
263 | "source": [
264 | "## ElementTree"
265 | ]
266 | },
267 | {
268 | "cell_type": "code",
269 | "execution_count": null,
270 | "metadata": {
271 | "collapsed": false,
272 | "slideshow": {
273 | "slide_type": "subslide"
274 | }
275 | },
276 | "outputs": [],
277 | "source": [
278 | "# čtení\n",
279 | "from xml.etree.ElementTree import parse\n",
280 | "\n",
281 | "# přečtení souboru\n",
282 | "with open(\"data/books.xml\", mode=\"r\", encoding=\"utf-8\") as f:\n",
283 | " tree = parse(f)\n",
284 | "\n",
285 | "# projití elementů\n",
286 | "for book in tree.getroot():\n",
287 | " id = book.attrib[\"id\"]\n",
288 | " title = book.find(\"title\").text\n",
289 | " print(id, title)"
290 | ]
291 | },
292 | {
293 | "cell_type": "code",
294 | "execution_count": null,
295 | "metadata": {
296 | "collapsed": false,
297 | "slideshow": {
298 | "slide_type": "subslide"
299 | }
300 | },
301 | "outputs": [],
302 | "source": [
303 | "# podpora XPath (omezená)\n",
304 | "tree.findall(r\"book[genre='Fantasy']\")"
305 | ]
306 | },
307 | {
308 | "cell_type": "code",
309 | "execution_count": null,
310 | "metadata": {
311 | "collapsed": false,
312 | "slideshow": {
313 | "slide_type": "fragment"
314 | }
315 | },
316 | "outputs": [],
317 | "source": [
318 | "# podpora generátorů\n",
319 | "[el.text for el in tree.iterfind(r\"book/title\")]"
320 | ]
321 | },
322 | {
323 | "cell_type": "code",
324 | "execution_count": null,
325 | "metadata": {
326 | "collapsed": false,
327 | "slideshow": {
328 | "slide_type": "subslide"
329 | }
330 | },
331 | "outputs": [],
332 | "source": [
333 | "# úpravy dat\n",
334 | "for book in tree.iter(\"book\"):\n",
335 | " book.attrib[\"processed\"] = \"yes\"\n",
336 | "\n",
337 | "# zápis\n",
338 | "tree.write(\"data/books_processed.xml\", encoding=\"utf-8\")"
339 | ]
340 | },
341 | {
342 | "cell_type": "markdown",
343 | "metadata": {
344 | "slideshow": {
345 | "slide_type": "subslide"
346 | }
347 | },
348 | "source": [
349 | "## SAX"
350 | ]
351 | },
352 | {
353 | "cell_type": "code",
354 | "execution_count": null,
355 | "metadata": {
356 | "collapsed": true,
357 | "slideshow": {
358 | "slide_type": "subslide"
359 | }
360 | },
361 | "outputs": [],
362 | "source": [
363 | "from xml.sax import parse\n",
364 | "from xml.sax.handler import ContentHandler"
365 | ]
366 | },
367 | {
368 | "cell_type": "code",
369 | "execution_count": null,
370 | "metadata": {
371 | "collapsed": true,
372 | "slideshow": {
373 | "slide_type": "fragment"
374 | }
375 | },
376 | "outputs": [],
377 | "source": [
378 | "# vytvořím parser\n",
379 | "class GenreCollector(ContentHandler):\n",
380 | "\n",
381 | " def __init__(self):\n",
382 | " self.genres = set()\n",
383 | " self._in_genre_tag = False\n",
384 | " \n",
385 | " def startElement(self, name, attrs):\n",
386 | " if name == \"genre\":\n",
387 | " self._in_genre_tag = True\n",
388 | "\n",
389 | " def endElement(self, name):\n",
390 | " if name == \"genre\":\n",
391 | " self._in_genre_tag = False\n",
392 | "\n",
393 | " def characters(self, data):\n",
394 | " if self._in_genre_tag:\n",
395 | " self.genres.add(data)"
396 | ]
397 | },
398 | {
399 | "cell_type": "code",
400 | "execution_count": null,
401 | "metadata": {
402 | "collapsed": false,
403 | "slideshow": {
404 | "slide_type": "subslide"
405 | }
406 | },
407 | "outputs": [],
408 | "source": [
409 | "# pustím ho na data\n",
410 | "with open(\"data/books.xml\", mode=\"r\", encoding=\"utf-8\") as books_file:\n",
411 | " collector = GenreCollector()\n",
412 | " parse(books_file, collector)\n",
413 | " print(collector.genres)"
414 | ]
415 | },
416 | {
417 | "cell_type": "markdown",
418 | "metadata": {
419 | "slideshow": {
420 | "slide_type": "subslide"
421 | }
422 | },
423 | "source": [
424 | "Všechny zmiňované parsery obsahují:\n",
425 | "\n",
426 | "- pro práci s namespacovaným XML – suffix metody nebo parametr `NS`\n",
427 | "- metody pro načtení dokumentu z řetězce, ne ze souboru"
428 | ]
429 | },
430 | {
431 | "cell_type": "markdown",
432 | "metadata": {
433 | "slideshow": {
434 | "slide_type": "subslide"
435 | }
436 | },
437 | "source": [
438 | "## Zápis XML"
439 | ]
440 | },
441 | {
442 | "cell_type": "markdown",
443 | "metadata": {
444 | "slideshow": {
445 | "slide_type": "fragment"
446 | }
447 | },
448 | "source": [
449 | "Nebuďte masochisti, použijte [Jinju](http://jinja.pocoo.org/)."
450 | ]
451 | },
452 | {
453 | "cell_type": "code",
454 | "execution_count": null,
455 | "metadata": {
456 | "collapsed": true,
457 | "slideshow": {
458 | "slide_type": "subslide"
459 | }
460 | },
461 | "outputs": [],
462 | "source": [
463 | "# jinja2 není ve standardní knihovně\n",
464 | "from jinja2 import Template\n",
465 | "import datetime\n",
466 | "\n",
467 | "books = [\n",
468 | " {\n",
469 | " \"id\": 1,\n",
470 | " \"author\": \"Me\",\n",
471 | " \"title\": \"About me\",\n",
472 | " \"genre\": \"Science\",\n",
473 | " \"price\": 123.2456,\n",
474 | " \"date\": datetime.date.today(),\n",
475 | " },\n",
476 | "]"
477 | ]
478 | },
479 | {
480 | "cell_type": "code",
481 | "execution_count": null,
482 | "metadata": {
483 | "collapsed": false,
484 | "slideshow": {
485 | "slide_type": "subslide"
486 | }
487 | },
488 | "outputs": [],
489 | "source": [
490 | "# načtení šablony\n",
491 | "with open(\"data/books.j2\", mode=\"r\", encoding=\"utf-8\") as f:\n",
492 | " template = Template(f.read())\n",
493 | "\n",
494 | "# vykreslení\n",
495 | "print(template.render(books=books))"
496 | ]
497 | },
498 | {
499 | "cell_type": "markdown",
500 | "metadata": {
501 | "slideshow": {
502 | "slide_type": "slide"
503 | }
504 | },
505 | "source": [
506 | "# YAML\n",
507 | "\n",
508 | "= YAML Ain't Markup Language"
509 | ]
510 | },
511 | {
512 | "cell_type": "code",
513 | "execution_count": null,
514 | "metadata": {
515 | "collapsed": false,
516 | "slideshow": {
517 | "slide_type": "subslide"
518 | }
519 | },
520 | "outputs": [],
521 | "source": [
522 | "# modul PyYaml není ve standardní knihovně\n",
523 | "import yaml"
524 | ]
525 | },
526 | {
527 | "cell_type": "code",
528 | "execution_count": null,
529 | "metadata": {
530 | "collapsed": false,
531 | "slideshow": {
532 | "slide_type": "fragment"
533 | }
534 | },
535 | "outputs": [],
536 | "source": [
537 | "# čtení\n",
538 | "with open(\"data/employees.yaml\", mode=\"r\", encoding=\"utf-8\") as f:\n",
539 | " data = yaml.load(f) # ošetřit yaml.YAMLError\n",
540 | " \n",
541 | "print(type(data))\n",
542 | "pprint(data)"
543 | ]
544 | },
545 | {
546 | "cell_type": "code",
547 | "execution_count": null,
548 | "metadata": {
549 | "collapsed": true,
550 | "slideshow": {
551 | "slide_type": "subslide"
552 | }
553 | },
554 | "outputs": [],
555 | "source": [
556 | "# zápis\n",
557 | "with open(\"data/employees_write.yaml\", mode=\"w\", encoding=\"utf-8\") as f:\n",
558 | " yaml.dump(data, f)"
559 | ]
560 | },
561 | {
562 | "cell_type": "code",
563 | "execution_count": null,
564 | "metadata": {
565 | "collapsed": false,
566 | "slideshow": {
567 | "slide_type": "fragment"
568 | }
569 | },
570 | "outputs": [],
571 | "source": [
572 | "# manipulace s řetězci - metody samy rozpoznají vstupní typ\n",
573 | "yaml.load(\"\"\"\n",
574 | "- jedna\n",
575 | "- dva\n",
576 | "- tři\n",
577 | "\"\"\")\n",
578 | "yaml.dump([\"jedna\", \"dva\", \"tři\"])"
579 | ]
580 | },
581 | {
582 | "cell_type": "markdown",
583 | "metadata": {
584 | "slideshow": {
585 | "slide_type": "slide"
586 | }
587 | },
588 | "source": [
589 | "# INI\n",
590 | "\n",
591 | "> The name \"INI file\" comes from the commonly used filename extension `.INI`, which stands for \"initialization\". Other common initialization file extensions are `.CFG` and `.conf`."
592 | ]
593 | },
594 | {
595 | "cell_type": "code",
596 | "execution_count": null,
597 | "metadata": {
598 | "collapsed": true,
599 | "slideshow": {
600 | "slide_type": "subslide"
601 | }
602 | },
603 | "outputs": [],
604 | "source": [
605 | "import configparser"
606 | ]
607 | },
608 | {
609 | "cell_type": "code",
610 | "execution_count": null,
611 | "metadata": {
612 | "collapsed": false,
613 | "slideshow": {
614 | "slide_type": "fragment"
615 | }
616 | },
617 | "outputs": [],
618 | "source": [
619 | "# čtení\n",
620 | "config = configparser.ConfigParser()\n",
621 | "config.read(\"data/config.ini\", encoding=\"utf-8\")\n",
622 | "\n",
623 | "for server in config.sections():\n",
624 | " print(server, \" -- \", config[server][\"ForwardX11\"])"
625 | ]
626 | },
627 | {
628 | "cell_type": "code",
629 | "execution_count": null,
630 | "metadata": {
631 | "collapsed": false,
632 | "slideshow": {
633 | "slide_type": "fragment"
634 | }
635 | },
636 | "outputs": [],
637 | "source": [
638 | "# výchozí hodnoty\n",
639 | "config.defaults()"
640 | ]
641 | },
642 | {
643 | "cell_type": "code",
644 | "execution_count": null,
645 | "metadata": {
646 | "collapsed": false,
647 | "slideshow": {
648 | "slide_type": "subslide"
649 | }
650 | },
651 | "outputs": [],
652 | "source": [
653 | "# aktualizace konfigurace\n",
654 | "config[\"bitbucket.org\"][\"ForwardX11\"] = \"no\""
655 | ]
656 | },
657 | {
658 | "cell_type": "code",
659 | "execution_count": null,
660 | "metadata": {
661 | "collapsed": true,
662 | "slideshow": {
663 | "slide_type": "fragment"
664 | }
665 | },
666 | "outputs": [],
667 | "source": [
668 | "# zápis\n",
669 | "with open(\"data/config_updated.ini\", mode=\"w\", encoding=\"utf-8\") as f:\n",
670 | " config.write(f)"
671 | ]
672 | },
673 | {
674 | "cell_type": "markdown",
675 | "metadata": {
676 | "slideshow": {
677 | "slide_type": "slide"
678 | }
679 | },
680 | "source": [
681 | "# Příklad\n",
682 | "\n",
683 | "- Převeďte soubor `books.xml` na JSON."
684 | ]
685 | },
686 | {
687 | "cell_type": "code",
688 | "execution_count": null,
689 | "metadata": {
690 | "collapsed": true,
691 | "slideshow": {
692 | "slide_type": "skip"
693 | }
694 | },
695 | "outputs": [],
696 | "source": [
697 | "import json\n",
698 | "\n",
699 | "# TODO"
700 | ]
701 | }
702 | ],
703 | "metadata": {
704 | "celltoolbar": "Slideshow",
705 | "kernelspec": {
706 | "display_name": "Python 3",
707 | "language": "python",
708 | "name": "python3"
709 | },
710 | "language_info": {
711 | "codemirror_mode": {
712 | "name": "ipython",
713 | "version": 3
714 | },
715 | "file_extension": ".py",
716 | "mimetype": "text/x-python",
717 | "name": "python",
718 | "nbconvert_exporter": "python",
719 | "pygments_lexer": "ipython3",
720 | "version": "3.5.2"
721 | }
722 | },
723 | "nbformat": 4,
724 | "nbformat_minor": 0
725 | }
726 |
--------------------------------------------------------------------------------
/09-databaze-perzistence.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# Pickle\n",
12 | "\n",
13 | "Umožňuje binárně \"zmrazit\" prakticky libovolná data."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {
20 | "collapsed": true,
21 | "slideshow": {
22 | "slide_type": "fragment"
23 | }
24 | },
25 | "outputs": [],
26 | "source": [
27 | "import pickle"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": null,
33 | "metadata": {
34 | "collapsed": true,
35 | "slideshow": {
36 | "slide_type": "subslide"
37 | }
38 | },
39 | "outputs": [],
40 | "source": [
41 | "# struktury\n",
42 | "data = {\n",
43 | " \"velmi\": \"slozity\",\n",
44 | " \"slovnik\": [\"slozeny\", \"z\", 1.2, \"klicu\"],\n",
45 | " \"a\": {\"dalsich\", \"divnych\", \"veci\"},\n",
46 | " (1, 2): False,\n",
47 | " 5: None,\n",
48 | "}"
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": null,
54 | "metadata": {
55 | "collapsed": false,
56 | "slideshow": {
57 | "slide_type": "fragment"
58 | }
59 | },
60 | "outputs": [],
61 | "source": [
62 | "# zápis do souboru\n",
63 | "with open(\"data/pickle.p\", mode=\"wb\") as f:\n",
64 | " pickle.dump(data, f)"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": null,
70 | "metadata": {
71 | "collapsed": false,
72 | "slideshow": {
73 | "slide_type": "fragment"
74 | }
75 | },
76 | "outputs": [],
77 | "source": [
78 | "# zapiklení do objektu `bytes`\n",
79 | "pickle.dumps(data)[:64] # zkráceno .."
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": null,
85 | "metadata": {
86 | "collapsed": false,
87 | "slideshow": {
88 | "slide_type": "fragment"
89 | }
90 | },
91 | "outputs": [],
92 | "source": [
93 | "# načtení ze souboru\n",
94 | "with open(\"data/pickle.p\", mode=\"rb\") as f:\n",
95 | " print(pickle.load(f))"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {
101 | "slideshow": {
102 | "slide_type": "subslide"
103 | }
104 | },
105 | "source": [
106 | "**Co lze piklit?**\n",
107 | "\n",
108 | "- `None`, `True`, `False`\n",
109 | "- celá, reálná a komplexní čísla\n",
110 | "- řetězce, `bytes` a `bytearray`\n",
111 | "- n-tice, seznamy, množiny a slovníky s piklitelnými daty\n",
112 | "- běžné funkce (ne uzávěry, ne lambdy)\n",
113 | "- třídy (ne vnořené)\n",
114 | "- instance tříd, jejichž atribut `__dict__` nebo návratová hodnota metody `__getstate__()` je piklitelná"
115 | ]
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "metadata": {
120 | "slideshow": {
121 | "slide_type": "subslide"
122 | }
123 | },
124 | "source": [
125 | "U tříd a funkcí se piklí jenom *plné jméno objektu, ne kód*! U instancí navíc jejich data.\n",
126 | "\n",
127 | "Co to znamená?"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": null,
133 | "metadata": {
134 | "collapsed": false,
135 | "slideshow": {
136 | "slide_type": "fragment"
137 | }
138 | },
139 | "outputs": [],
140 | "source": [
141 | "def udelej_vec():\n",
142 | " print(\"Dělám věc.\")\n",
143 | "\n",
144 | "zapiklena_funkce = pickle.dumps(udelej_vec)\n",
145 | "\n",
146 | "# -------- přenos dat --------\n",
147 | "\n",
148 | "def udelej_vec():\n",
149 | " print(\"Dělám VELMI ZLOU věc.\")\n",
150 | "\n",
151 | "odpiklena_funkce = pickle.loads(zapiklena_funkce)\n",
152 | "odpiklena_funkce()"
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": null,
158 | "metadata": {
159 | "collapsed": false,
160 | "slideshow": {
161 | "slide_type": "subslide"
162 | }
163 | },
164 | "outputs": [],
165 | "source": [
166 | "# chyby\n",
167 | "try:\n",
168 | " pickle.dumps(lambda x: x ** 2)\n",
169 | "\n",
170 | "except pickle.PickleError as e:\n",
171 | " print(e)\n",
172 | "\n",
173 | "except RecursionError:\n",
174 | " print(\"We cannot go deeper.\")"
175 | ]
176 | },
177 | {
178 | "cell_type": "markdown",
179 | "metadata": {
180 | "slideshow": {
181 | "slide_type": "subslide"
182 | }
183 | },
184 | "source": [
185 | "**Nikdy nerozpiklujte cizí data.**"
186 | ]
187 | },
188 | {
189 | "cell_type": "markdown",
190 | "metadata": {
191 | "slideshow": {
192 | "slide_type": "slide"
193 | }
194 | },
195 | "source": [
196 | "# Shelve\n",
197 | "\n",
198 | "= Automaticky piklící slovník."
199 | ]
200 | },
201 | {
202 | "cell_type": "code",
203 | "execution_count": null,
204 | "metadata": {
205 | "collapsed": true,
206 | "slideshow": {
207 | "slide_type": "fragment"
208 | }
209 | },
210 | "outputs": [],
211 | "source": [
212 | "import shelve"
213 | ]
214 | },
215 | {
216 | "cell_type": "code",
217 | "execution_count": null,
218 | "metadata": {
219 | "collapsed": false,
220 | "slideshow": {
221 | "slide_type": "subslide"
222 | }
223 | },
224 | "outputs": [],
225 | "source": [
226 | "# zápis\n",
227 | "with shelve.open(\"data/storage\") as storage:\n",
228 | " storage[\"description\"] = \"dangerous content\"\n",
229 | " storage[\"function\"] = abs"
230 | ]
231 | },
232 | {
233 | "cell_type": "code",
234 | "execution_count": null,
235 | "metadata": {
236 | "collapsed": false,
237 | "slideshow": {
238 | "slide_type": "fragment"
239 | }
240 | },
241 | "outputs": [],
242 | "source": [
243 | "# čtení = ten samý protokol! :-)\n",
244 | "with shelve.open(\"data/storage\") as storage:\n",
245 | " print(dict(storage))"
246 | ]
247 | },
248 | {
249 | "cell_type": "markdown",
250 | "metadata": {
251 | "slideshow": {
252 | "slide_type": "subslide"
253 | }
254 | },
255 | "source": [
256 | "**Nikdy nerozpiklujte cizí data.**"
257 | ]
258 | },
259 | {
260 | "cell_type": "markdown",
261 | "metadata": {
262 | "slideshow": {
263 | "slide_type": "slide"
264 | }
265 | },
266 | "source": [
267 | "# [PEP249](https://www.python.org/dev/peps/pep-0249/) – Python Database API Specification 2.0"
268 | ]
269 | },
270 | {
271 | "cell_type": "markdown",
272 | "metadata": {
273 | "slideshow": {
274 | "slide_type": "subslide"
275 | }
276 | },
277 | "source": [
278 | "Každý DB modul by měl splňovat:\n",
279 | "\n",
280 | "- `modul.connect()` – vytvoření spojení\n",
281 | "- `connection.cursor()` – vytvoření kurzoru\n",
282 | "- `cursor.execute()` – vykonání dotazu\n",
283 | "- `cursor.fetchall()` – vytažení výsledků dotazu\n",
284 | "- `cursor.rowcount` – počet ovlivněných (vybraných) řádků dotazem\n",
285 | "- `connection.close()` – uzavření spojení"
286 | ]
287 | },
288 | {
289 | "cell_type": "markdown",
290 | "metadata": {
291 | "slideshow": {
292 | "slide_type": "slide"
293 | }
294 | },
295 | "source": [
296 | "# SQLite3\n",
297 | "\n",
298 | "= Nenáročná, relativně hloupá DB."
299 | ]
300 | },
301 | {
302 | "cell_type": "code",
303 | "execution_count": null,
304 | "metadata": {
305 | "collapsed": true,
306 | "slideshow": {
307 | "slide_type": "fragment"
308 | }
309 | },
310 | "outputs": [],
311 | "source": [
312 | "import sqlite3 # splňuje PEP249 - DB-API 2.0"
313 | ]
314 | },
315 | {
316 | "cell_type": "code",
317 | "execution_count": null,
318 | "metadata": {
319 | "collapsed": false,
320 | "slideshow": {
321 | "slide_type": "subslide"
322 | }
323 | },
324 | "outputs": [],
325 | "source": [
326 | "# vytvoření spojení a kurzoru\n",
327 | "connection = sqlite3.connect(\":memory:\")\n",
328 | "c = connection.cursor()"
329 | ]
330 | },
331 | {
332 | "cell_type": "code",
333 | "execution_count": null,
334 | "metadata": {
335 | "collapsed": false,
336 | "slideshow": {
337 | "slide_type": "fragment"
338 | }
339 | },
340 | "outputs": [],
341 | "source": [
342 | "# vytvoření tabulky DB\n",
343 | "c.execute(\"\"\"\n",
344 | "CREATE TABLE IF NOT EXISTS samples\n",
345 | "(id INTEGER PRIMARY KEY AUTOINCREMENT, value REAL);\n",
346 | "\"\"\")"
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "execution_count": null,
352 | "metadata": {
353 | "collapsed": false,
354 | "slideshow": {
355 | "slide_type": "fragment"
356 | }
357 | },
358 | "outputs": [],
359 | "source": [
360 | "from random import random\n",
361 | "\n",
362 | "# naplnění\n",
363 | "for i in range(10):\n",
364 | " params = (random(), ) # tuple\n",
365 | " c.execute(\"INSERT INTO samples (value) VALUES (?)\", params)\n",
366 | "\n",
367 | "# potvrzení transakce\n",
368 | "connection.commit()"
369 | ]
370 | },
371 | {
372 | "cell_type": "code",
373 | "execution_count": null,
374 | "metadata": {
375 | "collapsed": false,
376 | "slideshow": {
377 | "slide_type": "subslide"
378 | }
379 | },
380 | "outputs": [],
381 | "source": [
382 | "# výběr\n",
383 | "c.execute(\"SELECT * FROM samples\")\n",
384 | "\n",
385 | "# SQLite3 implementuje metodu `__iter__` u kurzoru, jinak => `fetchall`\n",
386 | "for sample in c:\n",
387 | " print(sample)"
388 | ]
389 | },
390 | {
391 | "cell_type": "code",
392 | "execution_count": null,
393 | "metadata": {
394 | "collapsed": false,
395 | "slideshow": {
396 | "slide_type": "subslide"
397 | }
398 | },
399 | "outputs": [],
400 | "source": [
401 | "# jiný obal pro vracená data\n",
402 | "connection.row_factory = sqlite3.Row\n",
403 | "\n",
404 | "# musí být před vytvořením kurzoru\n",
405 | "advanced_cursor = connection.cursor()\n",
406 | "\n",
407 | "advanced_cursor.execute(\"SELECT * FROM samples\")\n",
408 | "for sample in advanced_cursor:\n",
409 | " print(dict(sample))"
410 | ]
411 | },
412 | {
413 | "cell_type": "code",
414 | "execution_count": null,
415 | "metadata": {
416 | "collapsed": false,
417 | "slideshow": {
418 | "slide_type": "subslide"
419 | }
420 | },
421 | "outputs": [],
422 | "source": [
423 | "# kontextový manažer vytvoří transakci\n",
424 | "with connection:\n",
425 | " # `connection.execute` = zkratka bez vytváření kurzoru\n",
426 | " connection.execute(\"INSERT INTO samples (value) VALUES (0)\") # nebude vloženo\n",
427 | " connection.execute(\"INVALID QUERY\")"
428 | ]
429 | },
430 | {
431 | "cell_type": "markdown",
432 | "metadata": {
433 | "slideshow": {
434 | "slide_type": "slide"
435 | }
436 | },
437 | "source": [
438 | "# ORM\n",
439 | "\n",
440 | "= Objektově relační mapování. Není ve standardní knihovně.\n",
441 | "\n",
442 | "- [SQLAlchemy](http://www.sqlalchemy.org/)\n",
443 | "- [peewee](http://peewee.readthedocs.io/en/latest/index.html)"
444 | ]
445 | },
446 | {
447 | "cell_type": "markdown",
448 | "metadata": {
449 | "slideshow": {
450 | "slide_type": "subslide"
451 | }
452 | },
453 | "source": [
454 | "## Peewee"
455 | ]
456 | },
457 | {
458 | "cell_type": "code",
459 | "execution_count": null,
460 | "metadata": {
461 | "collapsed": true,
462 | "slideshow": {
463 | "slide_type": "fragment"
464 | }
465 | },
466 | "outputs": [],
467 | "source": [
468 | "import peewee\n",
469 | "from datetime import date"
470 | ]
471 | },
472 | {
473 | "cell_type": "code",
474 | "execution_count": null,
475 | "metadata": {
476 | "collapsed": true,
477 | "slideshow": {
478 | "slide_type": "subslide"
479 | }
480 | },
481 | "outputs": [],
482 | "source": [
483 | "db = peewee.SqliteDatabase(\"data/people.db\")\n",
484 | "\n",
485 | "# společný předek pro vlastní modely\n",
486 | "class Model(peewee.Model):\n",
487 | " class Meta:\n",
488 | " database = db\n",
489 | "\n",
490 | "# vlastní model\n",
491 | "class Person(Model):\n",
492 | " name = peewee.CharField()\n",
493 | " birthday = peewee.DateField()"
494 | ]
495 | },
496 | {
497 | "cell_type": "code",
498 | "execution_count": null,
499 | "metadata": {
500 | "collapsed": true,
501 | "slideshow": {
502 | "slide_type": "subslide"
503 | }
504 | },
505 | "outputs": [],
506 | "source": [
507 | "db.connect()"
508 | ]
509 | },
510 | {
511 | "cell_type": "code",
512 | "execution_count": null,
513 | "metadata": {
514 | "collapsed": false,
515 | "slideshow": {
516 | "slide_type": "-"
517 | }
518 | },
519 | "outputs": [],
520 | "source": [
521 | "# toto se běžně nedělá\n",
522 | "if Person.table_exists():\n",
523 | " Person.drop_table()\n",
524 | "Person.create_table()"
525 | ]
526 | },
527 | {
528 | "cell_type": "code",
529 | "execution_count": null,
530 | "metadata": {
531 | "collapsed": false,
532 | "slideshow": {
533 | "slide_type": "fragment"
534 | }
535 | },
536 | "outputs": [],
537 | "source": [
538 | "# vytvoření záznamů\n",
539 | "Person.create(name=\"David\", birthday=date.today())\n",
540 | "luke = Person(name=\"Luke\", birthday=date(2002, 1, 3))\n",
541 | "luke.save()"
542 | ]
543 | },
544 | {
545 | "cell_type": "code",
546 | "execution_count": null,
547 | "metadata": {
548 | "collapsed": false,
549 | "slideshow": {
550 | "slide_type": "subslide"
551 | }
552 | },
553 | "outputs": [],
554 | "source": [
555 | "# výběr\n",
556 | "for person in Person.select():\n",
557 | " print(person.name, person.birthday)"
558 | ]
559 | },
560 | {
561 | "cell_type": "code",
562 | "execution_count": null,
563 | "metadata": {
564 | "collapsed": false,
565 | "slideshow": {
566 | "slide_type": "fragment"
567 | }
568 | },
569 | "outputs": [],
570 | "source": [
571 | "# aktualizace\n",
572 | "luke.birthday = date.today()\n",
573 | "luke.save()"
574 | ]
575 | },
576 | {
577 | "cell_type": "code",
578 | "execution_count": null,
579 | "metadata": {
580 | "collapsed": false,
581 | "slideshow": {
582 | "slide_type": "fragment"
583 | }
584 | },
585 | "outputs": [],
586 | "source": [
587 | "# filtrovaný výběr\n",
588 | "for person in Person.select().where(Person.name == \"Luke\"):\n",
589 | " print(person.birthday)"
590 | ]
591 | },
592 | {
593 | "cell_type": "markdown",
594 | "metadata": {
595 | "slideshow": {
596 | "slide_type": "subslide"
597 | }
598 | },
599 | "source": [
600 | "**Podporované backendy:**\n",
601 | "\n",
602 | "- SQLite (pomocí standardní knihovny)\n",
603 | "- MySQL – `pymysql`\n",
604 | "- PostgreQSL - `psycopg2`"
605 | ]
606 | },
607 | {
608 | "cell_type": "markdown",
609 | "metadata": {
610 | "slideshow": {
611 | "slide_type": "slide"
612 | }
613 | },
614 | "source": [
615 | "# Příklad\n",
616 | "\n",
617 | "- Přečtěte soubor `data/books.xml` a data z něj vložte do SQLite databáze `data/books.sqlite3`.\n",
618 | "- Vypište knihy, kde: `price > 10.0`.\n",
619 | "- *Profi varianta:* nainstalujte a použijte ORM."
620 | ]
621 | },
622 | {
623 | "cell_type": "code",
624 | "execution_count": null,
625 | "metadata": {
626 | "collapsed": true,
627 | "slideshow": {
628 | "slide_type": "skip"
629 | }
630 | },
631 | "outputs": [],
632 | "source": [
633 | "import sqlite3\n",
634 | "\n",
635 | "create_query = r\"\"\"\n",
636 | "CREATE TABLE IF NOT EXISTS books (\n",
637 | " id INTEGER PRIMARY KEY,\n",
638 | " title TEXT,\n",
639 | " author TEXT,\n",
640 | " genre TEXT,\n",
641 | " price FLOAT,\n",
642 | " publish_date DATE,\n",
643 | " description TEXT\n",
644 | ");\n",
645 | "\"\"\"\n",
646 | "\n",
647 | "# TODO"
648 | ]
649 | }
650 | ],
651 | "metadata": {
652 | "kernelspec": {
653 | "display_name": "Python 3",
654 | "language": "python",
655 | "name": "python3"
656 | },
657 | "language_info": {
658 | "codemirror_mode": {
659 | "name": "ipython",
660 | "version": 3
661 | },
662 | "file_extension": ".py",
663 | "mimetype": "text/x-python",
664 | "name": "python",
665 | "nbconvert_exporter": "python",
666 | "pygments_lexer": "ipython3",
667 | "version": "3.5.2"
668 | }
669 | },
670 | "nbformat": 4,
671 | "nbformat_minor": 0
672 | }
673 |
--------------------------------------------------------------------------------
/10-interakce-os-uzivatel.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {
7 | "collapsed": true,
8 | "slideshow": {
9 | "slide_type": "slide"
10 | }
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import sys"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "collapsed": false,
22 | "slideshow": {
23 | "slide_type": "subslide"
24 | }
25 | },
26 | "outputs": [],
27 | "source": [
28 | "# ukončení programu\n",
29 | "sys.exit()"
30 | ]
31 | },
32 | {
33 | "cell_type": "code",
34 | "execution_count": null,
35 | "metadata": {
36 | "collapsed": false,
37 | "slideshow": {
38 | "slide_type": "fragment"
39 | }
40 | },
41 | "outputs": [],
42 | "source": [
43 | "# argumenty skriptu\n",
44 | "sys.argv"
45 | ]
46 | },
47 | {
48 | "cell_type": "code",
49 | "execution_count": null,
50 | "metadata": {
51 | "collapsed": false,
52 | "slideshow": {
53 | "slide_type": "subslide"
54 | }
55 | },
56 | "outputs": [],
57 | "source": [
58 | "# proměnná cesty\n",
59 | "sys.path"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "execution_count": null,
65 | "metadata": {
66 | "collapsed": false,
67 | "slideshow": {
68 | "slide_type": "fragment"
69 | }
70 | },
71 | "outputs": [],
72 | "source": [
73 | "# platforma\n",
74 | "sys.platform"
75 | ]
76 | },
77 | {
78 | "cell_type": "markdown",
79 | "metadata": {
80 | "slideshow": {
81 | "slide_type": "slide"
82 | }
83 | },
84 | "source": [
85 | "# Úklid při ukončení programu"
86 | ]
87 | },
88 | {
89 | "cell_type": "code",
90 | "execution_count": null,
91 | "metadata": {
92 | "collapsed": true,
93 | "slideshow": {
94 | "slide_type": "-"
95 | }
96 | },
97 | "outputs": [],
98 | "source": [
99 | "import atexit"
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "execution_count": null,
105 | "metadata": {
106 | "collapsed": false,
107 | "slideshow": {
108 | "slide_type": "subslide"
109 | }
110 | },
111 | "outputs": [],
112 | "source": [
113 | "def uklid(jmeno):\n",
114 | " print(\"Uklízečka\", jmeno, \"se hlásí do služby!\")\n",
115 | "\n",
116 | "atexit.register(uklid, \"Jarmilka\")"
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": null,
122 | "metadata": {
123 | "collapsed": true,
124 | "slideshow": {
125 | "slide_type": "fragment"
126 | }
127 | },
128 | "outputs": [],
129 | "source": [
130 | "# elegantnější varianta (bez parametrů)\n",
131 | "@atexit.register\n",
132 | "def zamkni():\n",
133 | " print(\"Cvak.\")"
134 | ]
135 | },
136 | {
137 | "cell_type": "markdown",
138 | "metadata": {
139 | "slideshow": {
140 | "slide_type": "slide"
141 | }
142 | },
143 | "source": [
144 | "# Logování"
145 | ]
146 | },
147 | {
148 | "cell_type": "code",
149 | "execution_count": null,
150 | "metadata": {
151 | "collapsed": true,
152 | "slideshow": {
153 | "slide_type": "-"
154 | }
155 | },
156 | "outputs": [],
157 | "source": [
158 | "import logging\n",
159 | "logging.basicConfig()"
160 | ]
161 | },
162 | {
163 | "cell_type": "code",
164 | "execution_count": null,
165 | "metadata": {
166 | "collapsed": false,
167 | "slideshow": {
168 | "slide_type": "subslide"
169 | }
170 | },
171 | "outputs": [],
172 | "source": [
173 | "# přes získaný logger budeme logovat\n",
174 | "log = logging.getLogger(__name__)"
175 | ]
176 | },
177 | {
178 | "cell_type": "code",
179 | "execution_count": null,
180 | "metadata": {
181 | "collapsed": false,
182 | "slideshow": {
183 | "slide_type": "fragment"
184 | }
185 | },
186 | "outputs": [],
187 | "source": [
188 | "log.debug(\"Dělám operaci X.\")\n",
189 | "log.info(\"Operace X provedena.\")\n",
190 | "log.warning(\"Operace X nemohla být provedena kvůli špatnému vstupu.\")\n",
191 | "log.error(\"Provádění operace X selhalo.\")\n",
192 | "log.critical(\"OMG WTF!\")"
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "execution_count": null,
198 | "metadata": {
199 | "collapsed": false,
200 | "scrolled": true,
201 | "slideshow": {
202 | "slide_type": "subslide"
203 | }
204 | },
205 | "outputs": [],
206 | "source": [
207 | "# změna úrovně logování\n",
208 | "log.setLevel(logging.DEBUG)\n",
209 | "log.info(\"Hmm..\")"
210 | ]
211 | },
212 | {
213 | "cell_type": "code",
214 | "execution_count": null,
215 | "metadata": {
216 | "collapsed": false,
217 | "slideshow": {
218 | "slide_type": "fragment"
219 | }
220 | },
221 | "outputs": [],
222 | "source": [
223 | "# logování výjimek - funguje jako error\n",
224 | "try:\n",
225 | " raise ValueError(\"špatná hodnota\")\n",
226 | "except ValueError:\n",
227 | " log.exception(\"Nepovedlo se...\")"
228 | ]
229 | },
230 | {
231 | "cell_type": "markdown",
232 | "metadata": {
233 | "slideshow": {
234 | "slide_type": "subslide"
235 | }
236 | },
237 | "source": [
238 | "[Různé handlery](https://docs.python.org/3/howto/logging.html#useful-handlers).\n",
239 | "\n",
240 | "- do souboru\n",
241 | "- na konzoli\n",
242 | "- mailem\n",
243 | "- nikam\n",
244 | "\n",
245 | "[Filtry](https://docs.python.org/3/library/logging.html#filter-objects)."
246 | ]
247 | },
248 | {
249 | "cell_type": "markdown",
250 | "metadata": {
251 | "slideshow": {
252 | "slide_type": "slide"
253 | }
254 | },
255 | "source": [
256 | "# Datum a čas"
257 | ]
258 | },
259 | {
260 | "cell_type": "code",
261 | "execution_count": null,
262 | "metadata": {
263 | "collapsed": true,
264 | "slideshow": {
265 | "slide_type": "-"
266 | }
267 | },
268 | "outputs": [],
269 | "source": [
270 | "import time\n",
271 | "import datetime"
272 | ]
273 | },
274 | {
275 | "cell_type": "code",
276 | "execution_count": null,
277 | "metadata": {
278 | "collapsed": false,
279 | "slideshow": {
280 | "slide_type": "subslide"
281 | }
282 | },
283 | "outputs": [],
284 | "source": [
285 | "# dej si pauzu\n",
286 | "time.sleep(1)"
287 | ]
288 | },
289 | {
290 | "cell_type": "code",
291 | "execution_count": null,
292 | "metadata": {
293 | "collapsed": false,
294 | "slideshow": {
295 | "slide_type": "fragment"
296 | }
297 | },
298 | "outputs": [],
299 | "source": [
300 | "# časové razítko\n",
301 | "time.time()"
302 | ]
303 | },
304 | {
305 | "cell_type": "markdown",
306 | "metadata": {
307 | "slideshow": {
308 | "slide_type": "subslide"
309 | }
310 | },
311 | "source": [
312 | "- `datetime.date` = pouze datum\n",
313 | "- `datetime.time` = pouze čas\n",
314 | "- `datetime.datetime` = datum s časem\n",
315 | "- `datetime.timedelta` = časový interval"
316 | ]
317 | },
318 | {
319 | "cell_type": "code",
320 | "execution_count": null,
321 | "metadata": {
322 | "collapsed": false,
323 | "slideshow": {
324 | "slide_type": "fragment"
325 | }
326 | },
327 | "outputs": [],
328 | "source": [
329 | "silvestr = datetime.date(2016, 12, 31)\n",
330 | "poledne = datetime.time(12)\n",
331 | "ted = datetime.datetime.now()\n",
332 | "o_hodinu = datetime.timedelta(hours=1)"
333 | ]
334 | },
335 | {
336 | "cell_type": "code",
337 | "execution_count": null,
338 | "metadata": {
339 | "collapsed": false,
340 | "slideshow": {
341 | "slide_type": "subslide"
342 | }
343 | },
344 | "outputs": [],
345 | "source": [
346 | "# porovnání\n",
347 | "silvestr > datetime.date.today()"
348 | ]
349 | },
350 | {
351 | "cell_type": "code",
352 | "execution_count": null,
353 | "metadata": {
354 | "collapsed": false,
355 | "slideshow": {
356 | "slide_type": "fragment"
357 | }
358 | },
359 | "outputs": [],
360 | "source": [
361 | "# kombinace \n",
362 | "datetime.datetime.combine(silvestr, poledne)"
363 | ]
364 | },
365 | {
366 | "cell_type": "code",
367 | "execution_count": null,
368 | "metadata": {
369 | "collapsed": false,
370 | "slideshow": {
371 | "slide_type": "fragment"
372 | }
373 | },
374 | "outputs": [],
375 | "source": [
376 | "# posuny\n",
377 | "datetime.datetime.now() - o_hodinu - o_hodinu"
378 | ]
379 | },
380 | {
381 | "cell_type": "code",
382 | "execution_count": null,
383 | "metadata": {
384 | "collapsed": false,
385 | "slideshow": {
386 | "slide_type": "subslide"
387 | }
388 | },
389 | "outputs": [],
390 | "source": [
391 | "# výpis\n",
392 | "print(ted.year, ted.month, ted.second, sep=\" ---- \")\n",
393 | "print(\"{:%d.%m.%Y, %H:%M:%S}\".format(ted))"
394 | ]
395 | },
396 | {
397 | "cell_type": "code",
398 | "execution_count": null,
399 | "metadata": {
400 | "collapsed": false,
401 | "slideshow": {
402 | "slide_type": "fragment"
403 | }
404 | },
405 | "outputs": [],
406 | "source": [
407 | "# parsování času\n",
408 | "cas = \"26.07.2016, 22:37:11\"\n",
409 | "datetime.datetime.strptime(cas, \"%d.%m.%Y, %H:%M:%S\")"
410 | ]
411 | },
412 | {
413 | "cell_type": "markdown",
414 | "metadata": {
415 | "slideshow": {
416 | "slide_type": "slide"
417 | }
418 | },
419 | "source": [
420 | "# Parsování argumentů"
421 | ]
422 | },
423 | {
424 | "cell_type": "code",
425 | "execution_count": null,
426 | "metadata": {
427 | "collapsed": false,
428 | "slideshow": {
429 | "slide_type": "subslide"
430 | }
431 | },
432 | "outputs": [],
433 | "source": [
434 | "# NE\n",
435 | "import sys\n",
436 | "if sys.argv[1] == \"notebook\":\n",
437 | " spustit_notebook()\n",
438 | "else:\n",
439 | " print(\"nápověda...\")"
440 | ]
441 | },
442 | {
443 | "cell_type": "code",
444 | "execution_count": null,
445 | "metadata": {
446 | "collapsed": false,
447 | "slideshow": {
448 | "slide_type": "subslide"
449 | }
450 | },
451 | "outputs": [],
452 | "source": [
453 | "# lepší, ale zbytečně složité\n",
454 | "import argparse\n",
455 | "parser = argparse.ArgumentParser(description='Process some integers.')\n",
456 | "parser.add_argument('integers', metavar='N', type=int, nargs='+',\n",
457 | " help='an integer for the accumulator')\n",
458 | "parser.add_argument('--sum', dest='function', action='store_const',\n",
459 | " const=sum, default=max,\n",
460 | " help='sum the integers (default: find the max)')\n",
461 | "args = parser.parse_args([\"--sum\", \"1\", \"2\", \"4\"])\n",
462 | "print(args)"
463 | ]
464 | },
465 | {
466 | "cell_type": "markdown",
467 | "metadata": {
468 | "slideshow": {
469 | "slide_type": "slide"
470 | }
471 | },
472 | "source": [
473 | "## [Click](click.pocoo.org/6/)\n",
474 | "\n",
475 | "= Command Line Interface Creation Kit\n",
476 | "\n",
477 | "```bash\n",
478 | "pip3 install click\n",
479 | "```"
480 | ]
481 | },
482 | {
483 | "cell_type": "code",
484 | "execution_count": null,
485 | "metadata": {
486 | "collapsed": false,
487 | "slideshow": {
488 | "slide_type": "-"
489 | }
490 | },
491 | "outputs": [],
492 | "source": [
493 | "import click"
494 | ]
495 | },
496 | {
497 | "cell_type": "code",
498 | "execution_count": null,
499 | "metadata": {
500 | "collapsed": false,
501 | "slideshow": {
502 | "slide_type": "subslide"
503 | }
504 | },
505 | "outputs": [],
506 | "source": [
507 | "@click.command()\n",
508 | "@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n",
509 | "@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\n",
510 | "def hello(count, name):\n",
511 | " \"\"\"Greets NAME for a total of COUNT times.\"\"\"\n",
512 | " for x in range(count):\n",
513 | " print(\"Hello {}!\".format(name))\n",
514 | "\n",
515 | "\n",
516 | "# tohle není běžné\n",
517 | "sys.argv = \"./greeter.py --count=3 --name=David\".split()\n",
518 | "# sys.argv = \"./greeter.py --help\".split()\n",
519 | "# sys.argv = \"./greeter.py\".split()\n",
520 | " \n",
521 | "if __name__ == \"__main__\":\n",
522 | " hello()"
523 | ]
524 | },
525 | {
526 | "cell_type": "code",
527 | "execution_count": null,
528 | "metadata": {
529 | "collapsed": false,
530 | "slideshow": {
531 | "slide_type": "subslide"
532 | }
533 | },
534 | "outputs": [],
535 | "source": [
536 | "@click.group()\n",
537 | "def cli():\n",
538 | " pass\n",
539 | "\n",
540 | "@click.command()\n",
541 | "def initdb():\n",
542 | " click.echo(\"Initialized the database\")\n",
543 | "\n",
544 | "@click.command()\n",
545 | "def dropdb():\n",
546 | " click.echo(\"Dropped the database\")\n",
547 | "\n",
548 | "cli.add_command(initdb)\n",
549 | "cli.add_command(dropdb)\n",
550 | "\n",
551 | "# tohle není běžné\n",
552 | "sys.argv = \"./db.py dropdb --help\".split()\n",
553 | " \n",
554 | "if __name__ == \"__main__\":\n",
555 | " cli()"
556 | ]
557 | },
558 | {
559 | "cell_type": "markdown",
560 | "metadata": {
561 | "slideshow": {
562 | "slide_type": "subslide"
563 | }
564 | },
565 | "source": [
566 | "\"Doplňkové\" možnosti `click`u:\n",
567 | " \n",
568 | "- Printing to Stdout\n",
569 | "- ANSI Colors\n",
570 | "- Pager Support\n",
571 | "- Screen Clearing\n",
572 | "- Getting Characters from Terminal\n",
573 | "- Waiting for Key Press\n",
574 | "- Launching Editors\n",
575 | "- Launching Applications\n",
576 | "- Printing Filenames\n",
577 | "- Standard Streams\n",
578 | "- Intelligent File Opening\n",
579 | "- Finding Application Folders\n",
580 | "- Showing Progress Bars"
581 | ]
582 | },
583 | {
584 | "cell_type": "code",
585 | "execution_count": null,
586 | "metadata": {
587 | "collapsed": false,
588 | "slideshow": {
589 | "slide_type": "subslide"
590 | }
591 | },
592 | "outputs": [],
593 | "source": [
594 | "value = click.prompt(\"Please enter a valid integer\", type=int, default=10)\n",
595 | "print(value)"
596 | ]
597 | },
598 | {
599 | "cell_type": "markdown",
600 | "metadata": {
601 | "slideshow": {
602 | "slide_type": "slide"
603 | }
604 | },
605 | "source": [
606 | "# Curses"
607 | ]
608 | },
609 | {
610 | "cell_type": "markdown",
611 | "metadata": {
612 | "slideshow": {
613 | "slide_type": "fragment"
614 | }
615 | },
616 | "source": [
617 | "Nepoužívejte."
618 | ]
619 | },
620 | {
621 | "cell_type": "markdown",
622 | "metadata": {
623 | "slideshow": {
624 | "slide_type": "subslide"
625 | }
626 | },
627 | "source": [
628 | "## Urwid\n",
629 | "\n",
630 | ""
631 | ]
632 | },
633 | {
634 | "cell_type": "markdown",
635 | "metadata": {
636 | "slideshow": {
637 | "slide_type": "subslide"
638 | }
639 | },
640 | "source": [
641 | "Objektový přístup, dobrá dokumentace. Není ve standardní knihovně.\n",
642 | "\n",
643 | "```bash\n",
644 | "pip3 install urwid\n",
645 | "```\n",
646 | "\n",
647 | "[Tutoriál](http://urwid.org/tutorial/index.html)."
648 | ]
649 | },
650 | {
651 | "cell_type": "markdown",
652 | "metadata": {
653 | "collapsed": true,
654 | "slideshow": {
655 | "slide_type": "slide"
656 | }
657 | },
658 | "source": [
659 | "# Příklad\n",
660 | "\n",
661 | "- Nainstalujte si `click`.\n",
662 | "- Napište program, který vypočte čas posunutý o X od aktuálního.\n",
663 | "- Dále se řiďte pokyny v šabloně."
664 | ]
665 | },
666 | {
667 | "cell_type": "code",
668 | "execution_count": null,
669 | "metadata": {
670 | "collapsed": false,
671 | "slideshow": {
672 | "slide_type": "subslide"
673 | }
674 | },
675 | "outputs": [],
676 | "source": [
677 | "import click\n",
678 | "import atexit\n",
679 | "\n",
680 | "# TODO vyrobit logger\n",
681 | "\n",
682 | "# TODO vyrobit funkci, která při ukončení programu zaloguje debug \"ukončuji program\"\n",
683 | "\n",
684 | "# TODO přidat click dekorátory\n",
685 | "def time_shift(days, hours, minutes):\n",
686 | " # TODO zalogovat debug \"počítám čas\"\n",
687 | " # TODO vypočítat posunutý čas\n",
688 | " # TODO zalogovat info \"čas vypočten\"\n",
689 | " pass\n",
690 | "\n",
691 | "if __name__ == \"__main__\":\n",
692 | " time_shift()"
693 | ]
694 | }
695 | ],
696 | "metadata": {
697 | "kernelspec": {
698 | "display_name": "Python 3",
699 | "language": "python",
700 | "name": "python3"
701 | },
702 | "language_info": {
703 | "codemirror_mode": {
704 | "name": "ipython",
705 | "version": 3
706 | },
707 | "file_extension": ".py",
708 | "mimetype": "text/x-python",
709 | "name": "python",
710 | "nbconvert_exporter": "python",
711 | "pygments_lexer": "ipython3",
712 | "version": "3.5.2"
713 | }
714 | },
715 | "nbformat": 4,
716 | "nbformat_minor": 0
717 | }
--------------------------------------------------------------------------------
/11-web.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# Pracujeme s webem\n",
12 | "\n",
13 | "Aneb – co lze najít ve standardních knihovnách..."
14 | ]
15 | },
16 | {
17 | "cell_type": "markdown",
18 | "metadata": {
19 | "slideshow": {
20 | "slide_type": "subslide"
21 | }
22 | },
23 | "source": [
24 | "## HTTP server\n",
25 | "\n",
26 | "```\n",
27 | "python -m http.server\n",
28 | "```"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {
34 | "slideshow": {
35 | "slide_type": "subslide"
36 | }
37 | },
38 | "source": [
39 | "## [XML-RPC](https://cs.wikipedia.org/wiki/XML-RPC) klient"
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "execution_count": null,
45 | "metadata": {
46 | "collapsed": false,
47 | "slideshow": {
48 | "slide_type": "fragment"
49 | }
50 | },
51 | "outputs": [],
52 | "source": [
53 | "import xmlrpc.client \n",
54 | "\n",
55 | "with xmlrpc.client.ServerProxy(\"http://www.advogato.org/XMLRPC\") as remote:\n",
56 | " print(remote.test.capitalize(\"Hello World!\"))"
57 | ]
58 | },
59 | {
60 | "cell_type": "markdown",
61 | "metadata": {
62 | "slideshow": {
63 | "slide_type": "subslide"
64 | }
65 | },
66 | "source": [
67 | "Dnes nahrazován [SOAPem](https://cs.wikipedia.org/wiki/SOAP) = Simple Object Access Protocol.\n",
68 | "\n",
69 | "Láďa Hruška doporučuje: na SOAP použijte [Zeep](http://docs.python-zeep.org/en/latest/)."
70 | ]
71 | },
72 | {
73 | "cell_type": "markdown",
74 | "metadata": {
75 | "slideshow": {
76 | "slide_type": "subslide"
77 | }
78 | },
79 | "source": [
80 | "## Kódování"
81 | ]
82 | },
83 | {
84 | "cell_type": "code",
85 | "execution_count": null,
86 | "metadata": {
87 | "collapsed": true,
88 | "slideshow": {
89 | "slide_type": "-"
90 | }
91 | },
92 | "outputs": [],
93 | "source": [
94 | "import codecs"
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "execution_count": null,
100 | "metadata": {
101 | "collapsed": false,
102 | "slideshow": {
103 | "slide_type": "fragment"
104 | }
105 | },
106 | "outputs": [],
107 | "source": [
108 | "# base64\n",
109 | "zakodovano = codecs.encode(b\"surova data\", \"base64\")\n",
110 | "print(zakodovano)\n",
111 | "codecs.decode(zakodovano, \"base64\")"
112 | ]
113 | },
114 | {
115 | "cell_type": "markdown",
116 | "metadata": {
117 | "slideshow": {
118 | "slide_type": "slide"
119 | }
120 | },
121 | "source": [
122 | "# Stahujeme webové stránky"
123 | ]
124 | },
125 | {
126 | "cell_type": "markdown",
127 | "metadata": {
128 | "slideshow": {
129 | "slide_type": "fragment"
130 | }
131 | },
132 | "source": [
133 | "Standardní modul `urllib.request` – NE.\n",
134 | "\n",
135 | "- problémy s kódováním\n",
136 | "- ukecaný\n",
137 | "- horší dokumentace"
138 | ]
139 | },
140 | {
141 | "cell_type": "markdown",
142 | "metadata": {
143 | "slideshow": {
144 | "slide_type": "subslide"
145 | }
146 | },
147 | "source": [
148 | "## [Requests](http://docs.python-requests.org/en/master/)\n",
149 | "\n",
150 | "```\n",
151 | "pip3 install requests\n",
152 | "```"
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": null,
158 | "metadata": {
159 | "collapsed": true,
160 | "slideshow": {
161 | "slide_type": "-"
162 | }
163 | },
164 | "outputs": [],
165 | "source": [
166 | "import requests"
167 | ]
168 | },
169 | {
170 | "cell_type": "code",
171 | "execution_count": null,
172 | "metadata": {
173 | "collapsed": false,
174 | "slideshow": {
175 | "slide_type": "subslide"
176 | }
177 | },
178 | "outputs": [],
179 | "source": [
180 | "# stažení XML výstrahy\n",
181 | "url = \"http://portal.chmi.cz/files/portal/docs/meteo/om/zpravy/data/sivs_aktual.xml\"\n",
182 | "response = requests.get(url)\n",
183 | "print(response.text[:100]) # zkráceno\n",
184 | "\n",
185 | "# TODO parsování pomocí modulu xml.etree"
186 | ]
187 | },
188 | {
189 | "cell_type": "code",
190 | "execution_count": null,
191 | "metadata": {
192 | "collapsed": false,
193 | "slideshow": {
194 | "slide_type": "subslide"
195 | }
196 | },
197 | "outputs": [],
198 | "source": [
199 | "# stažení CSV rušení radarů\n",
200 | "response = requests.get(\"http://radar4ctu.bourky.cz/parse_ruseni.php\")\n",
201 | "print(response.text[:200]) # zkráceno\n",
202 | "\n",
203 | "# TODO parsování pomocí modulu csv, delimiter=\";\""
204 | ]
205 | },
206 | {
207 | "cell_type": "code",
208 | "execution_count": null,
209 | "metadata": {
210 | "collapsed": false,
211 | "slideshow": {
212 | "slide_type": "subslide"
213 | }
214 | },
215 | "outputs": [],
216 | "source": [
217 | "# JSON, parametry\n",
218 | "r = requests.get(\"https://httpbin.org/get\", params={\"non\": \"sense\"})\n",
219 | "r_dict = r.json()\n",
220 | "print(r_dict)\n",
221 | "r_dict[\"origin\"]"
222 | ]
223 | },
224 | {
225 | "cell_type": "code",
226 | "execution_count": null,
227 | "metadata": {
228 | "collapsed": false,
229 | "slideshow": {
230 | "slide_type": "subslide"
231 | }
232 | },
233 | "outputs": [],
234 | "source": [
235 | "# POST (DELETE, OPTION, ...)\n",
236 | "r = requests.post(\"http://httpbin.org/post\", data={\"key\": \"value\"})\n",
237 | "r.json()"
238 | ]
239 | },
240 | {
241 | "cell_type": "code",
242 | "execution_count": null,
243 | "metadata": {
244 | "collapsed": false,
245 | "slideshow": {
246 | "slide_type": "subslide"
247 | }
248 | },
249 | "outputs": [],
250 | "source": [
251 | "# stažení obrázku\n",
252 | "from datetime import date, time, datetime, timedelta\n",
253 | "\n",
254 | "# sestavit URL\n",
255 | "yesterday = date.today() - timedelta(days=1)\n",
256 | "yesterday_noon = datetime.combine(yesterday, time(12))\n",
257 | "url_suffix = \"pacz23.z_max3d.{:%Y%m%d.%H%M}.0.png\".format(yesterday_noon)\n",
258 | "url = \"http://portal.chmi.cz/files/portal/docs/meteo/rad/data_tr_png_1km/{}\".format(url_suffix)\n",
259 | "\n",
260 | "# HTTP dotaz\n",
261 | "r = requests.get(url, stream=True)\n",
262 | "\n",
263 | "# vyvolat výjimku pokud selze\n",
264 | "r.raise_for_status()\n",
265 | "\n",
266 | "# uložit do souboru\n",
267 | "with open(\"data/radar.png\", mode=\"wb\") as f:\n",
268 | " for chunk in r.iter_content():\n",
269 | " f.write(chunk)\n",
270 | " \n",
271 | "print(\"downloaded radar image from {:%d.%m.%Y %H:%M}\".format(yesterday_noon))"
272 | ]
273 | },
274 | {
275 | "cell_type": "markdown",
276 | "metadata": {
277 | "slideshow": {
278 | "slide_type": "slide"
279 | }
280 | },
281 | "source": [
282 | "# Parsujeme webové stránky"
283 | ]
284 | },
285 | {
286 | "cell_type": "markdown",
287 | "metadata": {
288 | "slideshow": {
289 | "slide_type": "subslide"
290 | }
291 | },
292 | "source": [
293 | "## [BeautifulSoup4](https://beautiful-soup-4.readthedocs.io/en/latest/#quick-start)\n",
294 | "\n",
295 | "```\n",
296 | "pip3 install bs4\n",
297 | "```\n",
298 | "\n",
299 | "**Metody:**\n",
300 | "\n",
301 | "- `find(html_atributy=\"hodnota\")`\n",
302 | "- `find_all(html_atributy=\"hodnota\")`\n",
303 | "- `select(\"css-selektor\")`"
304 | ]
305 | },
306 | {
307 | "cell_type": "code",
308 | "execution_count": null,
309 | "metadata": {
310 | "collapsed": true,
311 | "slideshow": {
312 | "slide_type": "-"
313 | }
314 | },
315 | "outputs": [],
316 | "source": [
317 | "import bs4"
318 | ]
319 | },
320 | {
321 | "cell_type": "code",
322 | "execution_count": null,
323 | "metadata": {
324 | "collapsed": false,
325 | "slideshow": {
326 | "slide_type": "subslide"
327 | }
328 | },
329 | "outputs": [],
330 | "source": [
331 | "# stažení stránky\n",
332 | "r = requests.get(\"http://www.svatek.org/\")\n",
333 | "r.encoding = \"utf8\"\n",
334 | "\n",
335 | "# parsování HTML\n",
336 | "soup = bs4.BeautifulSoup(r.text, \"html.parser\")\n",
337 | "\n",
338 | "# hledání elementu\n",
339 | "svatek = soup.find(class_=\"svatek-head\").text\n",
340 | "print(svatek)"
341 | ]
342 | },
343 | {
344 | "cell_type": "markdown",
345 | "metadata": {
346 | "slideshow": {
347 | "slide_type": "slide"
348 | }
349 | },
350 | "source": [
351 | "# Příklad\n",
352 | "\n",
353 | "- Vypiště nějaké zajímavé informace z http://numbersapi.com/ (použijte `requests`).\n",
354 | "- Vyzkoušejte si doplnit do URL `?json` a zpracovat data (použijte argument `params` a metodu `json()`).\n",
355 | "- Vypněte si internet a zpracujte výjimky, které vzniknou."
356 | ]
357 | },
358 | {
359 | "cell_type": "code",
360 | "execution_count": null,
361 | "metadata": {
362 | "collapsed": true,
363 | "slideshow": {
364 | "slide_type": "skip"
365 | }
366 | },
367 | "outputs": [],
368 | "source": [
369 | "import requests\n",
370 | "\n",
371 | "# TODO"
372 | ]
373 | },
374 | {
375 | "cell_type": "markdown",
376 | "metadata": {
377 | "slideshow": {
378 | "slide_type": "slide"
379 | }
380 | },
381 | "source": [
382 | "# Příklad 2\n",
383 | "\n",
384 | "Stáhněte nejnovějších 5 obrázků z archivu [NASA Astronomy Picture of the Day](http://apod.nasa.gov/apod/archivepix.html).\n",
385 | "\n",
386 | "[Řešení k dispozici zde](https://github.com/tomasbedrich/web-scraping-in-python/blob/master/en/level1.py)."
387 | ]
388 | }
389 | ],
390 | "metadata": {
391 | "kernelspec": {
392 | "display_name": "Python 3",
393 | "language": "python",
394 | "name": "python3"
395 | },
396 | "language_info": {
397 | "codemirror_mode": {
398 | "name": "ipython",
399 | "version": 3
400 | },
401 | "file_extension": ".py",
402 | "mimetype": "text/x-python",
403 | "name": "python",
404 | "nbconvert_exporter": "python",
405 | "pygments_lexer": "ipython3",
406 | "version": "3.5.2"
407 | }
408 | },
409 | "nbformat": 4,
410 | "nbformat_minor": 0
411 | }
412 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM jupyter/base-notebook
2 |
3 | WORKDIR /notebooks
4 |
5 | RUN pip install pipenv
6 | COPY Pipfile Pipfile.lock ./
7 | RUN pipenv install --system --deploy --dev
8 |
9 | COPY img ./img
10 | COPY data ./data
11 | COPY *.ipynb ./
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Attribution-ShareAlike 4.0 International
2 |
3 | =======================================================================
4 |
5 | Creative Commons Corporation ("Creative Commons") is not a law firm and
6 | does not provide legal services or legal advice. Distribution of
7 | Creative Commons public licenses does not create a lawyer-client or
8 | other relationship. Creative Commons makes its licenses and related
9 | information available on an "as-is" basis. Creative Commons gives no
10 | warranties regarding its licenses, any material licensed under their
11 | terms and conditions, or any related information. Creative Commons
12 | disclaims all liability for damages resulting from their use to the
13 | fullest extent possible.
14 |
15 | Using Creative Commons Public Licenses
16 |
17 | Creative Commons public licenses provide a standard set of terms and
18 | conditions that creators and other rights holders may use to share
19 | original works of authorship and other material subject to copyright
20 | and certain other rights specified in the public license below. The
21 | following considerations are for informational purposes only, are not
22 | exhaustive, and do not form part of our licenses.
23 |
24 | Considerations for licensors: Our public licenses are
25 | intended for use by those authorized to give the public
26 | permission to use material in ways otherwise restricted by
27 | copyright and certain other rights. Our licenses are
28 | irrevocable. Licensors should read and understand the terms
29 | and conditions of the license they choose before applying it.
30 | Licensors should also secure all rights necessary before
31 | applying our licenses so that the public can reuse the
32 | material as expected. Licensors should clearly mark any
33 | material not subject to the license. This includes other CC-
34 | licensed material, or material used under an exception or
35 | limitation to copyright. More considerations for licensors:
36 | wiki.creativecommons.org/Considerations_for_licensors
37 |
38 | Considerations for the public: By using one of our public
39 | licenses, a licensor grants the public permission to use the
40 | licensed material under specified terms and conditions. If
41 | the licensor's permission is not necessary for any reason--for
42 | example, because of any applicable exception or limitation to
43 | copyright--then that use is not regulated by the license. Our
44 | licenses grant only permissions under copyright and certain
45 | other rights that a licensor has authority to grant. Use of
46 | the licensed material may still be restricted for other
47 | reasons, including because others have copyright or other
48 | rights in the material. A licensor may make special requests,
49 | such as asking that all changes be marked or described.
50 | Although not required by our licenses, you are encouraged to
51 | respect those requests where reasonable. More_considerations
52 | for the public:
53 | wiki.creativecommons.org/Considerations_for_licensees
54 |
55 | =======================================================================
56 |
57 | Creative Commons Attribution-ShareAlike 4.0 International Public
58 | License
59 |
60 | By exercising the Licensed Rights (defined below), You accept and agree
61 | to be bound by the terms and conditions of this Creative Commons
62 | Attribution-ShareAlike 4.0 International Public License ("Public
63 | License"). To the extent this Public License may be interpreted as a
64 | contract, You are granted the Licensed Rights in consideration of Your
65 | acceptance of these terms and conditions, and the Licensor grants You
66 | such rights in consideration of benefits the Licensor receives from
67 | making the Licensed Material available under these terms and
68 | conditions.
69 |
70 |
71 | Section 1 -- Definitions.
72 |
73 | a. Adapted Material means material subject to Copyright and Similar
74 | Rights that is derived from or based upon the Licensed Material
75 | and in which the Licensed Material is translated, altered,
76 | arranged, transformed, or otherwise modified in a manner requiring
77 | permission under the Copyright and Similar Rights held by the
78 | Licensor. For purposes of this Public License, where the Licensed
79 | Material is a musical work, performance, or sound recording,
80 | Adapted Material is always produced where the Licensed Material is
81 | synched in timed relation with a moving image.
82 |
83 | b. Adapter's License means the license You apply to Your Copyright
84 | and Similar Rights in Your contributions to Adapted Material in
85 | accordance with the terms and conditions of this Public License.
86 |
87 | c. BY-SA Compatible License means a license listed at
88 | creativecommons.org/compatiblelicenses, approved by Creative
89 | Commons as essentially the equivalent of this Public License.
90 |
91 | d. Copyright and Similar Rights means copyright and/or similar rights
92 | closely related to copyright including, without limitation,
93 | performance, broadcast, sound recording, and Sui Generis Database
94 | Rights, without regard to how the rights are labeled or
95 | categorized. For purposes of this Public License, the rights
96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
97 | Rights.
98 |
99 | e. Effective Technological Measures means those measures that, in the
100 | absence of proper authority, may not be circumvented under laws
101 | fulfilling obligations under Article 11 of the WIPO Copyright
102 | Treaty adopted on December 20, 1996, and/or similar international
103 | agreements.
104 |
105 | f. Exceptions and Limitations means fair use, fair dealing, and/or
106 | any other exception or limitation to Copyright and Similar Rights
107 | that applies to Your use of the Licensed Material.
108 |
109 | g. License Elements means the license attributes listed in the name
110 | of a Creative Commons Public License. The License Elements of this
111 | Public License are Attribution and ShareAlike.
112 |
113 | h. Licensed Material means the artistic or literary work, database,
114 | or other material to which the Licensor applied this Public
115 | License.
116 |
117 | i. Licensed Rights means the rights granted to You subject to the
118 | terms and conditions of this Public License, which are limited to
119 | all Copyright and Similar Rights that apply to Your use of the
120 | Licensed Material and that the Licensor has authority to license.
121 |
122 | j. Licensor means the individual(s) or entity(ies) granting rights
123 | under this Public License.
124 |
125 | k. Share means to provide material to the public by any means or
126 | process that requires permission under the Licensed Rights, such
127 | as reproduction, public display, public performance, distribution,
128 | dissemination, communication, or importation, and to make material
129 | available to the public including in ways that members of the
130 | public may access the material from a place and at a time
131 | individually chosen by them.
132 |
133 | l. Sui Generis Database Rights means rights other than copyright
134 | resulting from Directive 96/9/EC of the European Parliament and of
135 | the Council of 11 March 1996 on the legal protection of databases,
136 | as amended and/or succeeded, as well as other essentially
137 | equivalent rights anywhere in the world.
138 |
139 | m. You means the individual or entity exercising the Licensed Rights
140 | under this Public License. Your has a corresponding meaning.
141 |
142 |
143 | Section 2 -- Scope.
144 |
145 | a. License grant.
146 |
147 | 1. Subject to the terms and conditions of this Public License,
148 | the Licensor hereby grants You a worldwide, royalty-free,
149 | non-sublicensable, non-exclusive, irrevocable license to
150 | exercise the Licensed Rights in the Licensed Material to:
151 |
152 | a. reproduce and Share the Licensed Material, in whole or
153 | in part; and
154 |
155 | b. produce, reproduce, and Share Adapted Material.
156 |
157 | 2. Exceptions and Limitations. For the avoidance of doubt, where
158 | Exceptions and Limitations apply to Your use, this Public
159 | License does not apply, and You do not need to comply with
160 | its terms and conditions.
161 |
162 | 3. Term. The term of this Public License is specified in Section
163 | 6(a).
164 |
165 | 4. Media and formats; technical modifications allowed. The
166 | Licensor authorizes You to exercise the Licensed Rights in
167 | all media and formats whether now known or hereafter created,
168 | and to make technical modifications necessary to do so. The
169 | Licensor waives and/or agrees not to assert any right or
170 | authority to forbid You from making technical modifications
171 | necessary to exercise the Licensed Rights, including
172 | technical modifications necessary to circumvent Effective
173 | Technological Measures. For purposes of this Public License,
174 | simply making modifications authorized by this Section 2(a)
175 | (4) never produces Adapted Material.
176 |
177 | 5. Downstream recipients.
178 |
179 | a. Offer from the Licensor -- Licensed Material. Every
180 | recipient of the Licensed Material automatically
181 | receives an offer from the Licensor to exercise the
182 | Licensed Rights under the terms and conditions of this
183 | Public License.
184 |
185 | b. Additional offer from the Licensor -- Adapted Material.
186 | Every recipient of Adapted Material from You
187 | automatically receives an offer from the Licensor to
188 | exercise the Licensed Rights in the Adapted Material
189 | under the conditions of the Adapter's License You apply.
190 |
191 | c. No downstream restrictions. You may not offer or impose
192 | any additional or different terms or conditions on, or
193 | apply any Effective Technological Measures to, the
194 | Licensed Material if doing so restricts exercise of the
195 | Licensed Rights by any recipient of the Licensed
196 | Material.
197 |
198 | 6. No endorsement. Nothing in this Public License constitutes or
199 | may be construed as permission to assert or imply that You
200 | are, or that Your use of the Licensed Material is, connected
201 | with, or sponsored, endorsed, or granted official status by,
202 | the Licensor or others designated to receive attribution as
203 | provided in Section 3(a)(1)(A)(i).
204 |
205 | b. Other rights.
206 |
207 | 1. Moral rights, such as the right of integrity, are not
208 | licensed under this Public License, nor are publicity,
209 | privacy, and/or other similar personality rights; however, to
210 | the extent possible, the Licensor waives and/or agrees not to
211 | assert any such rights held by the Licensor to the limited
212 | extent necessary to allow You to exercise the Licensed
213 | Rights, but not otherwise.
214 |
215 | 2. Patent and trademark rights are not licensed under this
216 | Public License.
217 |
218 | 3. To the extent possible, the Licensor waives any right to
219 | collect royalties from You for the exercise of the Licensed
220 | Rights, whether directly or through a collecting society
221 | under any voluntary or waivable statutory or compulsory
222 | licensing scheme. In all other cases the Licensor expressly
223 | reserves any right to collect such royalties.
224 |
225 |
226 | Section 3 -- License Conditions.
227 |
228 | Your exercise of the Licensed Rights is expressly made subject to the
229 | following conditions.
230 |
231 | a. Attribution.
232 |
233 | 1. If You Share the Licensed Material (including in modified
234 | form), You must:
235 |
236 | a. retain the following if it is supplied by the Licensor
237 | with the Licensed Material:
238 |
239 | i. identification of the creator(s) of the Licensed
240 | Material and any others designated to receive
241 | attribution, in any reasonable manner requested by
242 | the Licensor (including by pseudonym if
243 | designated);
244 |
245 | ii. a copyright notice;
246 |
247 | iii. a notice that refers to this Public License;
248 |
249 | iv. a notice that refers to the disclaimer of
250 | warranties;
251 |
252 | v. a URI or hyperlink to the Licensed Material to the
253 | extent reasonably practicable;
254 |
255 | b. indicate if You modified the Licensed Material and
256 | retain an indication of any previous modifications; and
257 |
258 | c. indicate the Licensed Material is licensed under this
259 | Public License, and include the text of, or the URI or
260 | hyperlink to, this Public License.
261 |
262 | 2. You may satisfy the conditions in Section 3(a)(1) in any
263 | reasonable manner based on the medium, means, and context in
264 | which You Share the Licensed Material. For example, it may be
265 | reasonable to satisfy the conditions by providing a URI or
266 | hyperlink to a resource that includes the required
267 | information.
268 |
269 | 3. If requested by the Licensor, You must remove any of the
270 | information required by Section 3(a)(1)(A) to the extent
271 | reasonably practicable.
272 |
273 | b. ShareAlike.
274 |
275 | In addition to the conditions in Section 3(a), if You Share
276 | Adapted Material You produce, the following conditions also apply.
277 |
278 | 1. The Adapter's License You apply must be a Creative Commons
279 | license with the same License Elements, this version or
280 | later, or a BY-SA Compatible License.
281 |
282 | 2. You must include the text of, or the URI or hyperlink to, the
283 | Adapter's License You apply. You may satisfy this condition
284 | in any reasonable manner based on the medium, means, and
285 | context in which You Share Adapted Material.
286 |
287 | 3. You may not offer or impose any additional or different terms
288 | or conditions on, or apply any Effective Technological
289 | Measures to, Adapted Material that restrict exercise of the
290 | rights granted under the Adapter's License You apply.
291 |
292 |
293 | Section 4 -- Sui Generis Database Rights.
294 |
295 | Where the Licensed Rights include Sui Generis Database Rights that
296 | apply to Your use of the Licensed Material:
297 |
298 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
299 | to extract, reuse, reproduce, and Share all or a substantial
300 | portion of the contents of the database;
301 |
302 | b. if You include all or a substantial portion of the database
303 | contents in a database in which You have Sui Generis Database
304 | Rights, then the database in which You have Sui Generis Database
305 | Rights (but not its individual contents) is Adapted Material,
306 |
307 | including for purposes of Section 3(b); and
308 | c. You must comply with the conditions in Section 3(a) if You Share
309 | all or a substantial portion of the contents of the database.
310 |
311 | For the avoidance of doubt, this Section 4 supplements and does not
312 | replace Your obligations under this Public License where the Licensed
313 | Rights include other Copyright and Similar Rights.
314 |
315 |
316 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
317 |
318 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
319 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
320 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
321 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
322 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
323 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
324 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
325 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
326 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
327 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
328 |
329 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
330 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
331 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
332 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
333 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
334 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
335 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
336 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
337 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
338 |
339 | c. The disclaimer of warranties and limitation of liability provided
340 | above shall be interpreted in a manner that, to the extent
341 | possible, most closely approximates an absolute disclaimer and
342 | waiver of all liability.
343 |
344 |
345 | Section 6 -- Term and Termination.
346 |
347 | a. This Public License applies for the term of the Copyright and
348 | Similar Rights licensed here. However, if You fail to comply with
349 | this Public License, then Your rights under this Public License
350 | terminate automatically.
351 |
352 | b. Where Your right to use the Licensed Material has terminated under
353 | Section 6(a), it reinstates:
354 |
355 | 1. automatically as of the date the violation is cured, provided
356 | it is cured within 30 days of Your discovery of the
357 | violation; or
358 |
359 | 2. upon express reinstatement by the Licensor.
360 |
361 | For the avoidance of doubt, this Section 6(b) does not affect any
362 | right the Licensor may have to seek remedies for Your violations
363 | of this Public License.
364 |
365 | c. For the avoidance of doubt, the Licensor may also offer the
366 | Licensed Material under separate terms or conditions or stop
367 | distributing the Licensed Material at any time; however, doing so
368 | will not terminate this Public License.
369 |
370 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
371 | License.
372 |
373 |
374 | Section 7 -- Other Terms and Conditions.
375 |
376 | a. The Licensor shall not be bound by any additional or different
377 | terms or conditions communicated by You unless expressly agreed.
378 |
379 | b. Any arrangements, understandings, or agreements regarding the
380 | Licensed Material not stated herein are separate from and
381 | independent of the terms and conditions of this Public License.
382 |
383 |
384 | Section 8 -- Interpretation.
385 |
386 | a. For the avoidance of doubt, this Public License does not, and
387 | shall not be interpreted to, reduce, limit, restrict, or impose
388 | conditions on any use of the Licensed Material that could lawfully
389 | be made without permission under this Public License.
390 |
391 | b. To the extent possible, if any provision of this Public License is
392 | deemed unenforceable, it shall be automatically reformed to the
393 | minimum extent necessary to make it enforceable. If the provision
394 | cannot be reformed, it shall be severed from this Public License
395 | without affecting the enforceability of the remaining terms and
396 | conditions.
397 |
398 | c. No term or condition of this Public License will be waived and no
399 | failure to comply consented to unless expressly agreed to by the
400 | Licensor.
401 |
402 | d. Nothing in this Public License constitutes or may be interpreted
403 | as a limitation upon, or waiver of, any privileges and immunities
404 | that apply to the Licensor or You, including from the legal
405 | processes of any jurisdiction or authority.
406 |
407 |
408 | =======================================================================
409 |
410 | Creative Commons is not a party to its public
411 | licenses. Notwithstanding, Creative Commons may elect to apply one of
412 | its public licenses to material it publishes and in those instances
413 | will be considered the “Licensor.” The text of the Creative Commons
414 | public licenses is dedicated to the public domain under the CC0 Public
415 | Domain Dedication. Except for the limited purpose of indicating that
416 | material is shared under a Creative Commons public license or as
417 | otherwise permitted by the Creative Commons policies published at
418 | creativecommons.org/policies, Creative Commons does not authorize the
419 | use of the trademark "Creative Commons" or any other trademark or logo
420 | of Creative Commons without its prior written consent including,
421 | without limitation, in connection with any unauthorized modifications
422 | to any of its public licenses or any other arrangements,
423 | understandings, or agreements concerning use of licensed material. For
424 | the avoidance of doubt, this paragraph does not form part of the
425 | public licenses.
426 |
427 | Creative Commons may be contacted at creativecommons.org.
428 |
429 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 |
3 | url = "https://pypi.python.org/simple"
4 | verify_ssl = true
5 | name = "pypi"
6 |
7 |
8 | [packages]
9 |
10 | # jupyter = "==1.*" # Jupyter is already installed in Docker base image
11 | RISE = "==5.*"
12 |
13 | "beautifulsoup4" = "==4.*"
14 | "Jinja2" = "==2.*"
15 | peewee = "==3.*"
16 | PyYAML = "==5.*"
17 | requests = "==2.*"
18 |
19 | # requirements for https://github.com/tomasbedrich/skoleni-python-knihovny
20 | Flask = "==1.*"
21 | matplotlib = "==3.*"
22 | pyzmq = "==22.*"
23 | click = "==7.*"
24 |
25 |
26 | [dev-packages]
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Základy Pythonu 3 - materiály pro výuku
2 |
3 | ## Instalace a spuštění
4 |
5 | 1) **Je třeba mít nainstalovaný Docker.** Návod na instalaci pro Linux, Windows i Mac OS [lze najít na oficiálním webu](https://docs.docker.com/install/).
6 | 2) **Stáhněte si prosím tento repozitář.** Zelené tlačítko "Clone or download" > "Download ZIP", alternativně `git clone https://github.com/tomasbedrich/skoleni-python`.
7 | 3) **Stačí spustit `docker-compose up`** (uvnitř adresáře `skoleni-python`), chvíli počkat a pak kliknout na odkaz, který se objeví v konzoli: `Or copy and paste one of these URLs: http://127.0.0.1:8888/?token=xxxxxx`
8 |
--------------------------------------------------------------------------------
/data/books.j2:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% for book in books %}
4 |
5 | {{ book.author }}
6 | {{ book.title }}
7 | {{ book.genre }}
8 | {{ "{:.2f}".format(book.price) }}
9 | {{ book.date.strftime('%Y-%m-%d') }}
10 | {{ book.description or "No description." }}
11 |
12 | {% endfor %}
13 |
--------------------------------------------------------------------------------
/data/books.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Gambardella, Matthew
5 | XML Developer's Guide
6 | Computer
7 | 44.95
8 | 2000-10-01
9 | An in-depth look at creating applications
10 | with XML.
11 |
12 |
13 | Ralls, Kim
14 | Midnight Rain
15 | Fantasy
16 | 5.95
17 | 2000-12-16
18 | A former architect battles corporate zombies,
19 | an evil sorceress, and her own childhood to become queen
20 | of the world.
21 |
22 |
23 | Corets, Eva
24 | Maeve Ascendant
25 | Fantasy
26 | 5.95
27 | 2000-11-17
28 | After the collapse of a nanotechnology
29 | society in England, the young survivors lay the
30 | foundation for a new society.
31 |
32 |
33 | Corets, Eva
34 | Oberon's Legacy
35 | Fantasy
36 | 5.95
37 | 2001-03-10
38 | In post-apocalypse England, the mysterious
39 | agent known only as Oberon helps to create a new life
40 | for the inhabitants of London. Sequel to Maeve
41 | Ascendant.
42 |
43 |
44 | Corets, Eva
45 | The Sundered Grail
46 | Fantasy
47 | 5.95
48 | 2001-09-10
49 | The two daughters of Maeve, half-sisters,
50 | battle one another for control of England. Sequel to
51 | Oberon's Legacy.
52 |
53 |
54 | Randall, Cynthia
55 | Lover Birds
56 | Romance
57 | 4.95
58 | 2000-09-02
59 | When Carla meets Paul at an ornithology
60 | conference, tempers fly as feathers get ruffled.
61 |
62 |
63 | Thurman, Paula
64 | Splish Splash
65 | Romance
66 | 4.95
67 | 2000-11-02
68 | A deep sea diver finds true love twenty
69 | thousand leagues beneath the sea.
70 |
71 |
72 | Knorr, Stefan
73 | Creepy Crawlies
74 | Horror
75 | 4.95
76 | 2000-12-06
77 | An anthology of horror stories about roaches,
78 | centipedes, scorpions and other insects.
79 |
80 |
81 | Kress, Peter
82 | Paradox Lost
83 | Science Fiction
84 | 6.95
85 | 2000-11-02
86 | After an inadvertant trip through a Heisenberg
87 | Uncertainty Device, James Salway discovers the problems
88 | of being quantum.
89 |
90 |
91 | O'Brien, Tim
92 | Microsoft .NET: The Programming Bible
93 | Computer
94 | 36.95
95 | 2000-12-09
96 | Microsoft's .NET initiative is explored in
97 | detail in this deep programmer's reference.
98 |
99 |
100 | O'Brien, Tim
101 | MSXML3: A Comprehensive Guide
102 | Computer
103 | 36.95
104 | 2000-12-01
105 | The Microsoft MSXML3 parser is covered in
106 | detail, with attention to XML DOM interfaces, XSLT processing,
107 | SAX and more.
108 |
109 |
110 | Galos, Mike
111 | Visual Studio 7: A Comprehensive Guide
112 | Computer
113 | 49.95
114 | 2001-04-16
115 | Microsoft Visual Studio 7 is explored in depth,
116 | looking at how Visual Basic, Visual C++, C#, and ASP+ are
117 | integrated into a comprehensive development
118 | environment.
119 |
120 |
--------------------------------------------------------------------------------
/data/books_processed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Gambardella, Matthew
4 | XML Developer's Guide
5 | Computer
6 | 44.95
7 | 2000-10-01
8 | An in-depth look at creating applications
9 | with XML.
10 |
11 |
12 | Ralls, Kim
13 | Midnight Rain
14 | Fantasy
15 | 5.95
16 | 2000-12-16
17 | A former architect battles corporate zombies,
18 | an evil sorceress, and her own childhood to become queen
19 | of the world.
20 |
21 |
22 | Corets, Eva
23 | Maeve Ascendant
24 | Fantasy
25 | 5.95
26 | 2000-11-17
27 | After the collapse of a nanotechnology
28 | society in England, the young survivors lay the
29 | foundation for a new society.
30 |
31 |
32 | Corets, Eva
33 | Oberon's Legacy
34 | Fantasy
35 | 5.95
36 | 2001-03-10
37 | In post-apocalypse England, the mysterious
38 | agent known only as Oberon helps to create a new life
39 | for the inhabitants of London. Sequel to Maeve
40 | Ascendant.
41 |
42 |
43 | Corets, Eva
44 | The Sundered Grail
45 | Fantasy
46 | 5.95
47 | 2001-09-10
48 | The two daughters of Maeve, half-sisters,
49 | battle one another for control of England. Sequel to
50 | Oberon's Legacy.
51 |
52 |
53 | Randall, Cynthia
54 | Lover Birds
55 | Romance
56 | 4.95
57 | 2000-09-02
58 | When Carla meets Paul at an ornithology
59 | conference, tempers fly as feathers get ruffled.
60 |
61 |
62 | Thurman, Paula
63 | Splish Splash
64 | Romance
65 | 4.95
66 | 2000-11-02
67 | A deep sea diver finds true love twenty
68 | thousand leagues beneath the sea.
69 |
70 |
71 | Knorr, Stefan
72 | Creepy Crawlies
73 | Horror
74 | 4.95
75 | 2000-12-06
76 | An anthology of horror stories about roaches,
77 | centipedes, scorpions and other insects.
78 |
79 |
80 | Kress, Peter
81 | Paradox Lost
82 | Science Fiction
83 | 6.95
84 | 2000-11-02
85 | After an inadvertant trip through a Heisenberg
86 | Uncertainty Device, James Salway discovers the problems
87 | of being quantum.
88 |
89 |
90 | O'Brien, Tim
91 | Microsoft .NET: The Programming Bible
92 | Computer
93 | 36.95
94 | 2000-12-09
95 | Microsoft's .NET initiative is explored in
96 | detail in this deep programmer's reference.
97 |
98 |
99 | O'Brien, Tim
100 | MSXML3: A Comprehensive Guide
101 | Computer
102 | 36.95
103 | 2000-12-01
104 | The Microsoft MSXML3 parser is covered in
105 | detail, with attention to XML DOM interfaces, XSLT processing,
106 | SAX and more.
107 |
108 |
109 | Galos, Mike
110 | Visual Studio 7: A Comprehensive Guide
111 | Computer
112 | 49.95
113 | 2001-04-16
114 | Microsoft Visual Studio 7 is explored in depth,
115 | looking at how Visual Basic, Visual C++, C#, and ASP+ are
116 | integrated into a comprehensive development
117 | environment.
118 |
119 |
--------------------------------------------------------------------------------
/data/config.ini:
--------------------------------------------------------------------------------
1 | [DEFAULT]
2 | ServerAliveInterval = 45
3 | Compression = yes
4 | CompressionLevel = 9
5 | ForwardX11 = yes
6 |
7 | [bitbucket.org]
8 | User = hg
9 |
10 | [topsecret.server.com]
11 | Port = 50022
12 | ForwardX11 = no
--------------------------------------------------------------------------------
/data/config_updated.ini:
--------------------------------------------------------------------------------
1 | [DEFAULT]
2 | serveraliveinterval = 45
3 | compression = yes
4 | compressionlevel = 9
5 | forwardx11 = yes
6 |
7 | [bitbucket.org]
8 | user = hg
9 | forwardx11 = no
10 |
11 | [topsecret.server.com]
12 | port = 50022
13 | forwardx11 = no
14 |
15 |
--------------------------------------------------------------------------------
/data/employees.yaml:
--------------------------------------------------------------------------------
1 | - martin:
2 | name: Martin D'vloper
3 | job: Developer
4 | skills:
5 | - python
6 | - perl
7 | - pascal
8 | - tabitha:
9 | name: Tabitha Bitumen
10 | job: Developer
11 | skills:
12 | - lisp
13 | - fortran
14 | - erlang
--------------------------------------------------------------------------------
/data/employees_write.yaml:
--------------------------------------------------------------------------------
1 | - martin:
2 | job: Developer
3 | name: Martin D'vloper
4 | skills: [python, perl, pascal]
5 | - tabitha:
6 | job: Developer
7 | name: Tabitha Bitumen
8 | skills: [lisp, fortran, erlang]
9 |
--------------------------------------------------------------------------------
/data/leave-me-alone.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/data/leave-me-alone.txt
--------------------------------------------------------------------------------
/data/menu.csv:
--------------------------------------------------------------------------------
1 | Product Title,Price,Weight,Quantity,Description
2 | Wagyu Tenderloin Steak,,,,"The most decadent, succulent cut of beef, ever."
3 | Wagyu Tenderloin Steak,55 ,6 oz,,
4 | Wagyu Tenderloin Steak,65 ,9 oz,,
5 | Wagyu Tenderloin Steak,79 ,12 oz,,
6 | Lamb Chops,,,,These taste really good.
7 | Lamb Chops,20 ,,3 chops,
8 | Lamb Chops,40 ,,6 chops,
9 | Lamb Chops,60 ,,9 chops,
--------------------------------------------------------------------------------
/data/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-js-sample",
3 | "version": "0.2.0",
4 | "description": "A sample Node.js app using Express 4",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node index.js"
8 | },
9 | "dependencies": {
10 | "express": "^4.13.3"
11 | },
12 | "engines": {
13 | "node": "4.0.0"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/heroku/node-js-sample"
18 | },
19 | "keywords": [
20 | "node",
21 | "heroku",
22 | "express"
23 | ],
24 | "author": "Mark Pundsack",
25 | "contributors": [
26 | "Zeke Sikelianos (http://zeke.sikelianos.com)"
27 | ],
28 | "license": "MIT"
29 | }
30 |
--------------------------------------------------------------------------------
/data/people.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/data/people.db
--------------------------------------------------------------------------------
/data/pickle.p:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/data/pickle.p
--------------------------------------------------------------------------------
/data/slovnik.p:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/data/slovnik.p
--------------------------------------------------------------------------------
/data/storage.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/data/storage.db
--------------------------------------------------------------------------------
/data/widget.json:
--------------------------------------------------------------------------------
1 | {
2 | "widget": {
3 | "debug": "on",
4 | "window": {
5 | "title": "Sample Konfabulator Widget",
6 | "name": "main_window",
7 | "width": 500,
8 | "height": 500
9 | },
10 | "image": {
11 | "src": "Images/Sun.png",
12 | "name": "sun1",
13 | "hOffset": 250,
14 | "vOffset": 250,
15 | "alignment": "center"
16 | },
17 | "text": {
18 | "data": "Click Here",
19 | "size": 36,
20 | "style": "bold",
21 | "name": "text1",
22 | "hOffset": 250,
23 | "vOffset": 100,
24 | "alignment": "center",
25 | "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/data/widget_write.json:
--------------------------------------------------------------------------------
1 | {
2 | "widget": {
3 | "window": {
4 | "height": 640,
5 | "width": 480,
6 | "title": "Ahoj!",
7 | "name": null
8 | },
9 | "debug": "off",
10 | "text": {
11 | "size": 36,
12 | "data": "Click Here",
13 | "vOffset": 100,
14 | "style": "bold",
15 | "name": "text1",
16 | "hOffset": 250,
17 | "alignment": "center",
18 | "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/data/write.csv:
--------------------------------------------------------------------------------
1 | 234,12,425
2 | 212,553,34
3 | "zrada, ",text,s carkou
4 | 0,1,4
5 | 1,4,9
6 | 4,9,16
7 | 9,16,25
8 | 16,25,36
9 |
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | services:
4 | notebook:
5 | image: tomasbedrich/skoleni-python:latest
6 | # build: .
7 | volumes:
8 | - ./:/notebooks
9 | ports:
10 | - "8888:8888" # Jupyter notebooks
11 | - "5000:5000" # demo Flask app
12 | - "6633:6633" # ZMQ communication for demo Flask app
13 |
--------------------------------------------------------------------------------
/img/bloky.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/img/bloky.png
--------------------------------------------------------------------------------
/img/generators-everywhere.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/img/generators-everywhere.jpg
--------------------------------------------------------------------------------
/img/harry-python.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/img/harry-python.png
--------------------------------------------------------------------------------
/img/kasna-lambda.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/img/kasna-lambda.jpg
--------------------------------------------------------------------------------
/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/img/logo.png
--------------------------------------------------------------------------------
/img/oop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/img/oop.png
--------------------------------------------------------------------------------
/img/oop_trieda_vs_objekt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomasbedrich/skoleni-python/972310697021a20d427bdc366aa617585d222366/img/oop_trieda_vs_objekt.png
--------------------------------------------------------------------------------