├── .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 | "![kašna lambda](img/kasna-lambda.jpg)" 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 | "![Generators...](img/generators-everywhere.jpg)" 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\"\"\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 | "![Rozhraní](http://urwid.org/_images/tour2.png)" 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 --------------------------------------------------------------------------------