├── .gitignore ├── README.md └── python_tips.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | MANIFEST 2 | build 3 | dist 4 | _build 5 | docs/man/*.gz 6 | docs/source/api/generated 7 | docs/source/config/options 8 | docs/source/config/shortcuts/*.csv 9 | docs/source/savefig 10 | docs/source/interactive/magics-generated.txt 11 | docs/gh-pages 12 | jupyter_notebook/notebook/static/mathjax 13 | jupyter_notebook/static/style/*.map 14 | *.py[co] 15 | __pycache__ 16 | *.egg-info 17 | *~ 18 | *.bak 19 | .ipynb_checkpoints 20 | .tox 21 | .DS_Store 22 | \#*# 23 | .#* 24 | .cache 25 | .coverage 26 | *.swp 27 | .vscode 28 | .pytest_cache 29 | .python-version 30 | venv*/ 31 | .idea/ 32 | .mypy_cache/ 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python_tips 2 | Some helpful Python tips for quick [reference](https://github.com/Sreekiranar/python_tips/blob/main/python_tips.ipynb). 3 | -------------------------------------------------------------------------------- /python_tips.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Python Random Tips\n", 8 | "\n", 9 | "### Author: Sreekiran A R\n", 10 | "*MSc Artificial Intelligence & Machine Learning, University of Birmingham* -\n", 11 | "[LinkedIn](https://www.linkedin.com/in/sreekiran-a-r-3b05a1116/)" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Tips from solving HackerRank" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "\n", 26 | "### 1. Remove the duplicates from a string preserving the first occurance" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 3, 32 | "metadata": {}, 33 | "outputs": [ 34 | { 35 | "name": "stdout", 36 | "output_type": "stream", 37 | "text": [ 38 | "mpt\n" 39 | ] 40 | } 41 | ], 42 | "source": [ 43 | "foo = \"mppmt\"\n", 44 | "result = \"\".join(dict.fromkeys(foo))\n", 45 | "### dict will preserve the order of occurance since Python 3.7 \n", 46 | "print(result)" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "### 2. Find element in a list that is occuring only once using set operations" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 7, 59 | "metadata": {}, 60 | "outputs": [ 61 | { 62 | "name": "stdout", 63 | "output_type": "stream", 64 | "text": [ 65 | "1 5\n" 66 | ] 67 | } 68 | ], 69 | "source": [ 70 | "rooms = [1,2,2,3,3,4,4,5]\n", 71 | "### create two sets, one for adding when a new element comes, one for adding when an already existing element comes\n", 72 | "seta = set()\n", 73 | "setb = set()\n", 74 | "for i in rooms:\n", 75 | " if i in seta:\n", 76 | " setb.add(i)\n", 77 | " else:\n", 78 | " seta.add(i)\n", 79 | "### finally take difference to get only element occuring once\n", 80 | "print(*seta-setb)" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "### 3. Math tip to get the pattern 1,11,111,1111,....." 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 9, 93 | "metadata": {}, 94 | "outputs": [ 95 | { 96 | "name": "stdout", 97 | "output_type": "stream", 98 | "text": [ 99 | "1\n", 100 | "11\n", 101 | "111\n", 102 | "1111\n", 103 | "11111\n" 104 | ] 105 | } 106 | ], 107 | "source": [ 108 | "def pattern(n):\n", 109 | " for i in range(1,n+1):\n", 110 | " print(10**(i)//9)\n", 111 | "pattern(5)" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "### 4. itertools groupby" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 10, 124 | "metadata": {}, 125 | "outputs": [ 126 | { 127 | "name": "stdout", 128 | "output_type": "stream", 129 | "text": [ 130 | "['A', 'B', 'C', 'D', 'A', 'B']\n", 131 | "[['A', 'A', 'A', 'A'], ['B', 'B', 'B'], ['C', 'C'], ['D']]\n" 132 | ] 133 | } 134 | ], 135 | "source": [ 136 | "from itertools import groupby\n", 137 | "print([k for k, g in groupby('AAAABBBCCDAABBB')])\n", 138 | "print([list(g) for k, g in groupby('AAAABBBCCD')])" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "### 5. namedtuple, (tuples with index names)" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 3, 151 | "metadata": {}, 152 | "outputs": [ 153 | { 154 | "name": "stdout", 155 | "output_type": "stream", 156 | "text": [ 157 | "1000000 20 100\n" 158 | ] 159 | } 160 | ], 161 | "source": [ 162 | "from collections import namedtuple\n", 163 | "\n", 164 | "car = namedtuple('CAR','PRICE MILAGE SPEED')\n", 165 | "car_ob = car(1000000,20,100)\n", 166 | "print(car_ob.PRICE, car_ob.MILAGE, car_ob.SPEED)" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "### 6. Regex pattern to get alternating digit matches" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 13, 179 | "metadata": {}, 180 | "outputs": [], 181 | "source": [ 182 | "import re\n", 183 | "pattern = r\"(\\d)(?=\\d\\1)\"" 184 | ] 185 | }, 186 | { 187 | "cell_type": "raw", 188 | "metadata": {}, 189 | "source": [ 190 | "Explanation:\n", 191 | "(\\d): Match and capture a digit in group #1\n", 192 | "(?=: Start lookahead\n", 193 | "\\d: Match any digit\n", 194 | "\\1: Back-reference to captured group #1\n", 195 | "): End lookahead" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 15, 201 | "metadata": {}, 202 | "outputs": [ 203 | { 204 | "data": { 205 | "text/plain": [ 206 | "['1', '2', '1', '2']" 207 | ] 208 | }, 209 | "execution_count": 15, 210 | "metadata": {}, 211 | "output_type": "execute_result" 212 | } 213 | ], 214 | "source": [ 215 | "re.findall(pattern,'121212') ### note this captures only the alternating match, not the pair" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "### 7. Naming groups in regex match\n", 223 | "`?P` can be used to name the subgroups when doing a regex match" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": 20, 229 | "metadata": {}, 230 | "outputs": [ 231 | { 232 | "data": { 233 | "text/plain": [ 234 | "{'user': 'sreekiran', 'website': 'website', 'extension': 'com'}" 235 | ] 236 | }, 237 | "execution_count": 20, 238 | "metadata": {}, 239 | "output_type": "execute_result" 240 | } 241 | ], 242 | "source": [ 243 | "import re\n", 244 | "m = re.match(r'(?P\\w+)@(?P\\w+)\\.(?P\\w+)','sreekiran@website.com')\n", 245 | "m.groupdict()" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": {}, 251 | "source": [ 252 | "### 8. Find consequtive character matches in regex" 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": 29, 258 | "metadata": {}, 259 | "outputs": [ 260 | { 261 | "name": "stdout", 262 | "output_type": "stream", 263 | "text": [ 264 | "['pppp', 'ffff']\n" 265 | ] 266 | } 267 | ], 268 | "source": [ 269 | "import re\n", 270 | "s = r'ppppythonisffffun'\n", 271 | "### here trying to match 3 or more consequtive characters coming\n", 272 | "re.findall(r'((\\w)\\2{2,})', s)\n", 273 | "print([match[0] for match in re.findall(r'((\\w)\\2{2,})', s)])" 274 | ] 275 | }, 276 | { 277 | "cell_type": "raw", 278 | "metadata": {}, 279 | "source": [ 280 | "Explanation:\n", 281 | "(: start main group\n", 282 | "(\\w): Match any alphanumeric characters\n", 283 | "\\2: reference to the matched alphanumeric character\n", 284 | "{2,}: repeat the match atleast two times, there by getting atleast three matches\n", 285 | "): end group" 286 | ] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "metadata": {}, 291 | "source": [ 292 | "### 9. Find matches with overlap" 293 | ] 294 | }, 295 | { 296 | "cell_type": "markdown", 297 | "metadata": {}, 298 | "source": [ 299 | "- when we do normal regex match, once a match is found, it wont be considered for finding the next matches\n", 300 | "\n", 301 | "- eg: consider the example AABBAAA, I need to find all the instances where A is occuring twice consequently" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": 50, 307 | "metadata": {}, 308 | "outputs": [ 309 | { 310 | "data": { 311 | "text/plain": [ 312 | "['AA', 'AA']" 313 | ] 314 | }, 315 | "execution_count": 50, 316 | "metadata": {}, 317 | "output_type": "execute_result" 318 | } 319 | ], 320 | "source": [ 321 | "import re\n", 322 | "re.findall(r'AA','AABBAAA')\n" 323 | ] 324 | }, 325 | { 326 | "cell_type": "markdown", 327 | "metadata": {}, 328 | "source": [ 329 | "- Here we got only two matches, but ideally the last AAA, has two pairs AA, as the first pair was already considered for matching, we didnt get the second match as only one A was left" 330 | ] 331 | }, 332 | { 333 | "cell_type": "markdown", 334 | "metadata": {}, 335 | "source": [ 336 | "- To solve this, we use something call lookahead operator `?=` \n", 337 | "- The lookahead captures the text you're interested in, but the actual match is technically the zero-width substring before the lookahead, so the matches are technically non-overlapping" 338 | ] 339 | }, 340 | { 341 | "cell_type": "code", 342 | "execution_count": 51, 343 | "metadata": {}, 344 | "outputs": [ 345 | { 346 | "data": { 347 | "text/plain": [ 348 | "['AA', 'AA', 'AA']" 349 | ] 350 | }, 351 | "execution_count": 51, 352 | "metadata": {}, 353 | "output_type": "execute_result" 354 | } 355 | ], 356 | "source": [ 357 | "import re\n", 358 | "re.findall(r'(?=(AA))','AABBAAA')" 359 | ] 360 | }, 361 | { 362 | "cell_type": "markdown", 363 | "metadata": {}, 364 | "source": [ 365 | "### 10. List in which we can add or remove elements from both ends: Deque\n" 366 | ] 367 | }, 368 | { 369 | "cell_type": "markdown", 370 | "metadata": {}, 371 | "source": [ 372 | "**collections.deque()**:\n", 373 | "\n", 374 | "- A deque is a double-ended queue. It can be used to add or remove elements from both ends.\n", 375 | "\n", 376 | "- Deques support thread safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction." 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": 4, 382 | "metadata": {}, 383 | "outputs": [ 384 | { 385 | "data": { 386 | "text/plain": [ 387 | "deque([1])" 388 | ] 389 | }, 390 | "execution_count": 4, 391 | "metadata": {}, 392 | "output_type": "execute_result" 393 | } 394 | ], 395 | "source": [ 396 | "from collections import deque\n", 397 | "\n", 398 | "l1 = deque()\n", 399 | "l1.append(1)\n", 400 | "l1" 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": 55, 406 | "metadata": {}, 407 | "outputs": [ 408 | { 409 | "data": { 410 | "text/plain": [ 411 | "deque([1, 1, 2, 3])" 412 | ] 413 | }, 414 | "execution_count": 55, 415 | "metadata": {}, 416 | "output_type": "execute_result" 417 | } 418 | ], 419 | "source": [ 420 | "l1.extend([1,2,3])\n", 421 | "l1" 422 | ] 423 | }, 424 | { 425 | "cell_type": "code", 426 | "execution_count": 56, 427 | "metadata": {}, 428 | "outputs": [ 429 | { 430 | "data": { 431 | "text/plain": [ 432 | "deque([2, 1, 1, 2, 3])" 433 | ] 434 | }, 435 | "execution_count": 56, 436 | "metadata": {}, 437 | "output_type": "execute_result" 438 | } 439 | ], 440 | "source": [ 441 | "l1.appendleft(2)\n", 442 | "l1" 443 | ] 444 | }, 445 | { 446 | "cell_type": "code", 447 | "execution_count": 57, 448 | "metadata": {}, 449 | "outputs": [ 450 | { 451 | "data": { 452 | "text/plain": [ 453 | "deque([9, 8, 7, 2, 1, 1, 2, 3])" 454 | ] 455 | }, 456 | "execution_count": 57, 457 | "metadata": {}, 458 | "output_type": "execute_result" 459 | } 460 | ], 461 | "source": [ 462 | "l1.extendleft([7,8,9])\n", 463 | "l1" 464 | ] 465 | }, 466 | { 467 | "cell_type": "code", 468 | "execution_count": 58, 469 | "metadata": {}, 470 | "outputs": [ 471 | { 472 | "data": { 473 | "text/plain": [ 474 | "deque([9, 8, 7, 2, 1, 1, 2])" 475 | ] 476 | }, 477 | "execution_count": 58, 478 | "metadata": {}, 479 | "output_type": "execute_result" 480 | } 481 | ], 482 | "source": [ 483 | "l1.pop()\n", 484 | "l1" 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "execution_count": 59, 490 | "metadata": {}, 491 | "outputs": [ 492 | { 493 | "data": { 494 | "text/plain": [ 495 | "deque([8, 7, 2, 1, 1, 2])" 496 | ] 497 | }, 498 | "execution_count": 59, 499 | "metadata": {}, 500 | "output_type": "execute_result" 501 | } 502 | ], 503 | "source": [ 504 | "l1.popleft()\n", 505 | "l1" 506 | ] 507 | }, 508 | { 509 | "cell_type": "code", 510 | "execution_count": 62, 511 | "metadata": {}, 512 | "outputs": [ 513 | { 514 | "data": { 515 | "text/plain": [ 516 | "deque([2, 1, 1, 2, 7, 8])" 517 | ] 518 | }, 519 | "execution_count": 62, 520 | "metadata": {}, 521 | "output_type": "execute_result" 522 | } 523 | ], 524 | "source": [ 525 | "l1.reverse()\n", 526 | "l1" 527 | ] 528 | }, 529 | { 530 | "cell_type": "code", 531 | "execution_count": 63, 532 | "metadata": {}, 533 | "outputs": [], 534 | "source": [ 535 | "l1.rotate(3)" 536 | ] 537 | }, 538 | { 539 | "cell_type": "code", 540 | "execution_count": 64, 541 | "metadata": {}, 542 | "outputs": [ 543 | { 544 | "data": { 545 | "text/plain": [ 546 | "deque([2, 7, 8, 2, 1, 1])" 547 | ] 548 | }, 549 | "execution_count": 64, 550 | "metadata": {}, 551 | "output_type": "execute_result" 552 | } 553 | ], 554 | "source": [ 555 | "l1" 556 | ] 557 | }, 558 | { 559 | "cell_type": "markdown", 560 | "metadata": {}, 561 | "source": [ 562 | "---" 563 | ] 564 | }, 565 | { 566 | "cell_type": "markdown", 567 | "metadata": {}, 568 | "source": [ 569 | "## General Python tips" 570 | ] 571 | }, 572 | { 573 | "cell_type": "markdown", 574 | "metadata": {}, 575 | "source": [ 576 | "### 1. Adding an element to a sorted list, maintaining the order." 577 | ] 578 | }, 579 | { 580 | "cell_type": "markdown", 581 | "metadata": {}, 582 | "source": [ 583 | "Adding an element to a sorted list, maintaining the order.\n", 584 | "It will be very computationally expensive to sort the list again every time after adding a new element.\n", 585 | "There is a Python Standard Library called bisect which can help us here." 586 | ] 587 | }, 588 | { 589 | "cell_type": "code", 590 | "execution_count": 5, 591 | "metadata": {}, 592 | "outputs": [], 593 | "source": [ 594 | "import bisect\n", 595 | "sorted_list = [1,2,3,5]\n", 596 | "new_element = 4\n", 597 | "bisect.insort_left(sorted_list,new_element)" 598 | ] 599 | }, 600 | { 601 | "cell_type": "code", 602 | "execution_count": 6, 603 | "metadata": {}, 604 | "outputs": [ 605 | { 606 | "data": { 607 | "text/plain": [ 608 | "[1, 2, 3, 4, 5]" 609 | ] 610 | }, 611 | "execution_count": 6, 612 | "metadata": {}, 613 | "output_type": "execute_result" 614 | } 615 | ], 616 | "source": [ 617 | "sorted_list" 618 | ] 619 | }, 620 | { 621 | "cell_type": "markdown", 622 | "metadata": {}, 623 | "source": [ 624 | "- [Bisect Python documentation](https://docs.python.org/3/library/bisect.html) \n", 625 | "- [LinkedIn_post](https://www.linkedin.com/posts/sreekiranar_bisect-array-bisection-algorithm-activity-6715680837087711232-F6Sk)" 626 | ] 627 | }, 628 | { 629 | "cell_type": "markdown", 630 | "metadata": {}, 631 | "source": [ 632 | "### 2. Intersting usage of *sum* function\n", 633 | "\n", 634 | "- Did you know the sum function in Python can be used to flatten a list of lists?" 635 | ] 636 | }, 637 | { 638 | "cell_type": "code", 639 | "execution_count": 4, 640 | "metadata": {}, 641 | "outputs": [ 642 | { 643 | "data": { 644 | "text/plain": [ 645 | "[1, 2, 3, 3, 4, 5, 'a', 'b', 'c']" 646 | ] 647 | }, 648 | "execution_count": 4, 649 | "metadata": {}, 650 | "output_type": "execute_result" 651 | } 652 | ], 653 | "source": [ 654 | "sum([[1, 2, 3],[3, 4, 5],['a', 'b', 'c']], [])" 655 | ] 656 | }, 657 | { 658 | "cell_type": "markdown", 659 | "metadata": {}, 660 | "source": [ 661 | "As they say in the Zen of Python, Flat is better than nested :)\n", 662 | "- [Zen of Python](https://www.python.org/dev/peps/pep-0020/)\n", 663 | "- [LinkedIn post](https://www.linkedin.com/posts/sreekiranar_python-programming-lessons-activity-6728708314374504448-hmO7)" 664 | ] 665 | }, 666 | { 667 | "cell_type": "markdown", 668 | "metadata": {}, 669 | "source": [ 670 | "### 3. Splitting numpy array into N equal chunks" 671 | ] 672 | }, 673 | { 674 | "cell_type": "code", 675 | "execution_count": 8, 676 | "metadata": {}, 677 | "outputs": [], 678 | "source": [ 679 | "import numpy as np\n" 680 | ] 681 | }, 682 | { 683 | "cell_type": "code", 684 | "execution_count": 9, 685 | "metadata": {}, 686 | "outputs": [ 687 | { 688 | "data": { 689 | "text/plain": [ 690 | "[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]" 691 | ] 692 | }, 693 | "execution_count": 9, 694 | "metadata": {}, 695 | "output_type": "execute_result" 696 | } 697 | ], 698 | "source": [ 699 | "a = np.arange(9)\n", 700 | "np.split(a,3)" 701 | ] 702 | }, 703 | { 704 | "cell_type": "markdown", 705 | "metadata": {}, 706 | "source": [ 707 | "- **np.split** throws an error if the array cannot be split into equal sub arrays\n", 708 | "- Use **np.array_split** in those scenarios" 709 | ] 710 | }, 711 | { 712 | "cell_type": "code", 713 | "execution_count": 10, 714 | "metadata": {}, 715 | "outputs": [ 716 | { 717 | "data": { 718 | "text/plain": [ 719 | "[array([0, 1, 2]), array([3, 4, 5]), array([6, 7])]" 720 | ] 721 | }, 722 | "execution_count": 10, 723 | "metadata": {}, 724 | "output_type": "execute_result" 725 | } 726 | ], 727 | "source": [ 728 | "a = np.arange(0,8)\n", 729 | "np.array_split(a,3)" 730 | ] 731 | }, 732 | { 733 | "cell_type": "markdown", 734 | "metadata": {}, 735 | "source": [ 736 | "When dealing with raw data, especially when doing mathematical computations for Machine Learning and Neural computation, we might need to flatten and reshape the arrays. Here are two useful functions which will help you to acheive your task." 737 | ] 738 | }, 739 | { 740 | "cell_type": "markdown", 741 | "metadata": {}, 742 | "source": [ 743 | "1. **np.squeeze()**: Make your list of lists into a single list" 744 | ] 745 | }, 746 | { 747 | "cell_type": "code", 748 | "execution_count": 11, 749 | "metadata": {}, 750 | "outputs": [ 751 | { 752 | "data": { 753 | "text/plain": [ 754 | "array([[[0]],\n", 755 | "\n", 756 | " [[1]],\n", 757 | "\n", 758 | " [[2]],\n", 759 | "\n", 760 | " [[3]],\n", 761 | "\n", 762 | " [[4]],\n", 763 | "\n", 764 | " [[5]],\n", 765 | "\n", 766 | " [[6]],\n", 767 | "\n", 768 | " [[7]],\n", 769 | "\n", 770 | " [[8]],\n", 771 | "\n", 772 | " [[9]]])" 773 | ] 774 | }, 775 | "execution_count": 11, 776 | "metadata": {}, 777 | "output_type": "execute_result" 778 | } 779 | ], 780 | "source": [ 781 | "a = np.arange(10).reshape(-1,1,1)\n", 782 | "a" 783 | ] 784 | }, 785 | { 786 | "cell_type": "code", 787 | "execution_count": 10, 788 | "metadata": {}, 789 | "outputs": [ 790 | { 791 | "data": { 792 | "text/plain": [ 793 | "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" 794 | ] 795 | }, 796 | "execution_count": 10, 797 | "metadata": {}, 798 | "output_type": "execute_result" 799 | } 800 | ], 801 | "source": [ 802 | "np.squeeze(a)" 803 | ] 804 | }, 805 | { 806 | "cell_type": "code", 807 | "execution_count": 14, 808 | "metadata": {}, 809 | "outputs": [ 810 | { 811 | "data": { 812 | "text/plain": [ 813 | "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" 814 | ] 815 | }, 816 | "execution_count": 14, 817 | "metadata": {}, 818 | "output_type": "execute_result" 819 | } 820 | ], 821 | "source": [ 822 | "a.flatten()" 823 | ] 824 | }, 825 | { 826 | "cell_type": "markdown", 827 | "metadata": {}, 828 | "source": [ 829 | "### 4. Priting a list in the reverse order without considering the last element" 830 | ] 831 | }, 832 | { 833 | "cell_type": "code", 834 | "execution_count": 12, 835 | "metadata": {}, 836 | "outputs": [ 837 | { 838 | "data": { 839 | "text/plain": [ 840 | "[4, 3, 2, 1]" 841 | ] 842 | }, 843 | "execution_count": 12, 844 | "metadata": {}, 845 | "output_type": "execute_result" 846 | } 847 | ], 848 | "source": [ 849 | "x = [1,2,3,4,5]\n", 850 | "### desired output: [4,3,2,1]\n", 851 | "x[-2::-1] ### (note the -2)" 852 | ] 853 | }, 854 | { 855 | "cell_type": "markdown", 856 | "metadata": {}, 857 | "source": [ 858 | "### 5. The walrus operator\n", 859 | "- There is a syntax in Python called Walrus operator \":=\" that assigns values to variables as part of a larger expression. Interestingly, the operator was affectionately named Walrus due to its resemblance to the eyes and tusks of a walrus! :D\n", 860 | "\n", 861 | "- This can be used to make your code more compact\n", 862 | "- For Example" 863 | ] 864 | }, 865 | { 866 | "cell_type": "code", 867 | "execution_count": 2, 868 | "metadata": {}, 869 | "outputs": [ 870 | { 871 | "name": "stdout", 872 | "output_type": "stream", 873 | "text": [ 874 | "10 is divisible by 5\n" 875 | ] 876 | } 877 | ], 878 | "source": [ 879 | "# without walrus\n", 880 | "count = 10\n", 881 | "if count % 5 == 0:\n", 882 | " print(f\"{count} is divisible by 5\")\n" 883 | ] 884 | }, 885 | { 886 | "cell_type": "code", 887 | "execution_count": 6, 888 | "metadata": {}, 889 | "outputs": [ 890 | { 891 | "name": "stdout", 892 | "output_type": "stream", 893 | "text": [ 894 | "10 is divisible by 5\n" 895 | ] 896 | } 897 | ], 898 | "source": [ 899 | "# with walrus\n", 900 | "if (count := 10) % 5 == 0:\n", 901 | " print(f\"{count} is divisible by 5\")" 902 | ] 903 | }, 904 | { 905 | "cell_type": "markdown", 906 | "metadata": {}, 907 | "source": [ 908 | "For more info: [What’s New In Python 3.8](https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions)" 909 | ] 910 | }, 911 | { 912 | "cell_type": "markdown", 913 | "metadata": {}, 914 | "source": [ 915 | "### 6. Progress Tracking made simpler" 916 | ] 917 | }, 918 | { 919 | "cell_type": "markdown", 920 | "metadata": {}, 921 | "source": [ 922 | "- Introducing a Python wrapper `tqdm` \n", 923 | "- tqdm derives from the Arabic word taqaddum (تقدّم) which can mean \"progress,\" and is an abbreviation for \"I love you so much\" in Spanish (te quiero demasiado)\n" 924 | ] 925 | }, 926 | { 927 | "cell_type": "markdown", 928 | "metadata": {}, 929 | "source": [ 930 | "#### Basic usage - Wrap `tqdm` around any iterables" 931 | ] 932 | }, 933 | { 934 | "cell_type": "code", 935 | "execution_count": 7, 936 | "metadata": {}, 937 | "outputs": [ 938 | { 939 | "name": "stderr", 940 | "output_type": "stream", 941 | "text": [ 942 | "100%|██████████| 5/5 [00:05<00:00, 1.01s/it]\n" 943 | ] 944 | } 945 | ], 946 | "source": [ 947 | "from tqdm import tqdm\n", 948 | "from time import sleep\n", 949 | "\n", 950 | "text = \"\"\n", 951 | "for char in tqdm([\"how\", \"long\", \"will\", \"it\", \"take\"]):\n", 952 | " ### this can be replaced with any operation required\n", 953 | " sleep(1)\n", 954 | " text = text + char" 955 | ] 956 | }, 957 | { 958 | "cell_type": "markdown", 959 | "metadata": {}, 960 | "source": [ 961 | "#### `trange(n)` - single call for tqdm(range(n))" 962 | ] 963 | }, 964 | { 965 | "cell_type": "code", 966 | "execution_count": 8, 967 | "metadata": {}, 968 | "outputs": [ 969 | { 970 | "name": "stderr", 971 | "output_type": "stream", 972 | "text": [ 973 | "100%|██████████| 100/100 [00:01<00:00, 85.20it/s]\n" 974 | ] 975 | } 976 | ], 977 | "source": [ 978 | "from tqdm import trange\n", 979 | "\n", 980 | "for i in trange(100):\n", 981 | " sleep(0.01)" 982 | ] 983 | }, 984 | { 985 | "cell_type": "markdown", 986 | "metadata": {}, 987 | "source": [ 988 | "- For information on customising the progress bar further, visit the official GitHub [page](https://github.com/tqdm/tqdm)." 989 | ] 990 | }, 991 | { 992 | "cell_type": "markdown", 993 | "metadata": {}, 994 | "source": [ 995 | "### 7. Enhance your terminal output using Rich" 996 | ] 997 | }, 998 | { 999 | "cell_type": "markdown", 1000 | "metadata": {}, 1001 | "source": [ 1002 | "- The rich library is a Python library for rendering rich text, tables, progress bars, syntax highlighted code, and even emojis to the terminal. \n", 1003 | "- It's designed to be easy to use and to make terminal output more visually appealing.\n", 1004 | "- Please visit the [Official Library](https://github.com/Textualize/rich) for more info.\n" 1005 | ] 1006 | }, 1007 | { 1008 | "cell_type": "code", 1009 | "execution_count": null, 1010 | "metadata": {}, 1011 | "outputs": [], 1012 | "source": [ 1013 | "!pip install rich" 1014 | ] 1015 | }, 1016 | { 1017 | "cell_type": "code", 1018 | "execution_count": 2, 1019 | "metadata": { 1020 | "scrolled": true 1021 | }, 1022 | "outputs": [ 1023 | { 1024 | "data": { 1025 | "text/html": [ 1026 | "
Wow! This is cool! Colors and emojis! 😄 😉\n",
1027 |        "
\n" 1028 | ], 1029 | "text/plain": [ 1030 | "" 1031 | ] 1032 | }, 1033 | "metadata": {}, 1034 | "output_type": "display_data" 1035 | } 1036 | ], 1037 | "source": [ 1038 | "from rich import print\n", 1039 | "\n", 1040 | "print(\"[blue]Wow! This is cool![/blue][green] Colors and emojis![/green] :smile: :wink:\")" 1041 | ] 1042 | }, 1043 | { 1044 | "cell_type": "code", 1045 | "execution_count": 3, 1046 | "metadata": {}, 1047 | "outputs": [ 1048 | { 1049 | "data": { 1050 | "application/vnd.jupyter.widget-view+json": { 1051 | "model_id": "f367d5a7c5184384af35b8fe6200a606", 1052 | "version_major": 2, 1053 | "version_minor": 0 1054 | }, 1055 | "text/plain": [ 1056 | "Output()" 1057 | ] 1058 | }, 1059 | "metadata": {}, 1060 | "output_type": "display_data" 1061 | } 1062 | ], 1063 | "source": [ 1064 | "from rich.progress import track\n", 1065 | "import time\n", 1066 | "\n", 1067 | "for _ in track(range(100)):\n", 1068 | " time.sleep(0.1)" 1069 | ] 1070 | } 1071 | ], 1072 | "metadata": { 1073 | "kernelspec": { 1074 | "display_name": "Python 3", 1075 | "language": "python", 1076 | "name": "python3" 1077 | }, 1078 | "language_info": { 1079 | "codemirror_mode": { 1080 | "name": "ipython", 1081 | "version": 3 1082 | }, 1083 | "file_extension": ".py", 1084 | "mimetype": "text/x-python", 1085 | "name": "python", 1086 | "nbconvert_exporter": "python", 1087 | "pygments_lexer": "ipython3", 1088 | "version": "3.8.2" 1089 | } 1090 | }, 1091 | "nbformat": 4, 1092 | "nbformat_minor": 4 1093 | } 1094 | --------------------------------------------------------------------------------