333 42 2MB
English Pages [1069] Year 2020
1000 Python Examples Gábor Szabó This book is for sale at http://leanpub.com/python-examples This version was published on 2020-09-21
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do. © 2020 Gábor Szabó
Contents Fixtures and Mocking in Python . . . . . . . . . . . How do you test Moon-landing? . . . . . . . . . How do you test a system … . . . . . . . . . . . . Plan . . . . . . . . . . . . . . . . . . . . . . . . . . . About me . . . . . . . . . . . . . . . . . . . . . . . Goal . . . . . . . . . . . . . . . . . . . . . . . . . . . Fixtures . . . . . . . . . . . . . . . . . . . . . . . . . Fixtuers in Pytest . . . . . . . . . . . . . . . . . . . Traditional xUnit fixtures . . . . . . . . . . . . . . Dependency Injection . . . . . . . . . . . . . . . . Temporary directory - tmpdir . . . . . . . . . . . Capture STDOUT and STDERR - capsys . . . . Home-made fixture . . . . . . . . . . . . . . . . . Home-made fixture - conftest . . . . . . . . . . . Home-made fixture with tempdir . . . . . . . . . Home-made fixture with yield . . . . . . . . . . . Fixture Autouse . . . . . . . . . . . . . . . . . . . . Fixture Autouse with yield . . . . . . . . . . . . . Fixture for MongoDB . . . . . . . . . . . . . . . . Test Doubles . . . . . . . . . . . . . . . . . . . . . . Test Doubles explained . . . . . . . . . . . . . . . Verify behavior or state? . . . . . . . . . . . . . . What is Mocking and Monkey Patching? . . . . Situations . . . . . . . . . . . . . . . . . . . . . . . Unit testing vs. Integration testing . . . . . . . . Experiment with mocking in various situations Examples are simple . . . . . . . . . . . . . . . . . Hard coded path . . . . . . . . . . . . . . . . . . . Manually Patching attribute . . . . . . . . . . . . Monkey Patching attribute . . . . . . . . . . . . . Monkey Patching functions . . . . . . . . . . . . . Monkey Patching dictionary items . . . . . . . . Mocking a whole class . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1 1 1 1 1 2 2 2 2 3 4 4 5 5 6 7 7 8 9 9 9 10 10 10 11 11 11 11 12 13 13 14 15
CONTENTS
Mocking input/output . . . . . . . . . . . Mocking input/output . . . . . . . . . . . Mocking random numbers . . . . . . . . Exercises . . . . . . . . . . . . . . . . . . . Work in pairs . . . . . . . . . . . . . . . . Exercise: test login expiration . . . . . . Solution: test login expiration . . . . . . Exercise: Record e-mail sending . . . . . Solution: Record e-mail sending . . . . . Exercise: Fixture database . . . . . . . . . Exercise: One Dimentsional space-fight Exercise: web client . . . . . . . . . . . . Exercise: Open WeatherMap client . . . Exercise: Mocking A Bank . . . . . . . . Testing the whole application . . . . . . Resources . . . . . . . . . . . . . . . . . . Retrospective . . . . . . . . . . . . . . . . Job searching help . . . . . . . . . . . . . Solutions - game . . . . . . . . . . . . . . Solutions - Mocking the database access First steps . . . . . . . . . . . . . . . . . . . . What is Python? . . . . . . . . . . . . . What is needed to write a program? . The source (code) of Python . . . . . . Python 2 vs. Python 3 . . . . . . . . . . Installation . . . . . . . . . . . . . . . . . Installation on Linux . . . . . . . . . . . Installation on Apple Mac OSX . . . . Installation on MS Windows . . . . . . Editors, IDEs . . . . . . . . . . . . . . . Documentation . . . . . . . . . . . . . . Program types . . . . . . . . . . . . . . . Python on the command line . . . . . . First script - hello world . . . . . . . . . Examples . . . . . . . . . . . . . . . . . . Comments . . . . . . . . . . . . . . . . . Variables . . . . . . . . . . . . . . . . . . Exercise: Hello world . . . . . . . . . . What is programming? . . . . . . . . . What are the programming languages A written human language . . . . . . . A programming language . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
15 16 17 17 17 17 18 19 20 21 21 23 23 24 26 27 27 27 27 29
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
31 31 31 32 32 32 33 33 33 34 36 36 36 37 37 37 38 38 38 38 39 39
CONTENTS
Words and punctuation matter! . Literals, Value Types in Python . Floating point limitation . . . . . Value Types in Numpy . . . . . . Rectangle (numerical operations) Multiply string . . . . . . . . . . . Add numbers . . . . . . . . . . . . Add strings . . . . . . . . . . . . . Exercise: Calculations . . . . . . . Solution: Calculations . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
39 39 40 40 41 41 42 42 43 43
Second steps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A main function . . . . . . . . . . . . . . . . . . . . . . . . . . The main function - called . . . . . . . . . . . . . . . . . . . . Indentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conditional main . . . . . . . . . . . . . . . . . . . . . . . . . . Input - Output I/O . . . . . . . . . . . . . . . . . . . . . . . . . print in Python 2 . . . . . . . . . . . . . . . . . . . . . . . . . . print in Python 3 . . . . . . . . . . . . . . . . . . . . . . . . . . print in Python 2 as if it was Python 3 . . . . . . . . . . . . . Exception: SyntaxError: Missing parentheses in call . . . . . Prompting for user input in Python 2 . . . . . . . . . . . . . . Prompting for user input in Python 3 . . . . . . . . . . . . . . Python2 input or raw_input? . . . . . . . . . . . . . . . . . . . Prompting both Python 2 and Python 3 . . . . . . . . . . . . Add numbers entered by the user (oups) . . . . . . . . . . . . Add numbers entered by the user (fixed) . . . . . . . . . . . How can I check if a string can be converted to a number? Converting string to int . . . . . . . . . . . . . . . . . . . . . . Converting float to int . . . . . . . . . . . . . . . . . . . . . . . Conditionals: if . . . . . . . . . . . . . . . . . . . . . . . . . . . Conditionals: if - else . . . . . . . . . . . . . . . . . . . . . . . Divide by 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conditionals: if - else (other example) . . . . . . . . . . . . . Conditionals: else if . . . . . . . . . . . . . . . . . . . . . . . . Conditionals: elif . . . . . . . . . . . . . . . . . . . . . . . . . . Ternary operator (Conditional Operator) . . . . . . . . . . . Case or Switch in Python . . . . . . . . . . . . . . . . . . . . . Exercise: Rectangle . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Calculator . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Age limit . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: What is this language? . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46 46 47 48 49 49 49 49 50 51 52 52 53 54 54 54 55 55 56 57 58 59 59 59 60 60 61 62 62 62 62 63
CONTENTS
Exercise: Standard Input . . . . . . Solution: Area of rectangle . . . . . Solution: Calculator . . . . . . . . . Solution: Calculator eval . . . . . . Solution: Age limit . . . . . . . . . . Solution: What is this language? . . Command line arguments . . . . . Command line arguments - len . . Command line arguments - exit . . Exercise: Rectangle (argv) . . . . . . Exercise: Calculator (argv) . . . . . Solution: Area of rectangle (argv) . Solution: Calculator (argv) . . . . . Solution: Calculator eval . . . . . . Compilation vs. Interpretation . . . Is Python compiled or interpreted? Flake8 checking . . . . . . . . . . . . Pylint checking . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
63 63 64 65 66 66 67 67 68 68 68 68 69 70 70 71 72 72
Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operators for Numbers . . . . . . . . . . . . . . . . . . . . . . . Integer division and the future . . . . . . . . . . . . . . . . . . Pseudo Random Number (unform distribution) . . . . . . . . Fixed random numbers . . . . . . . . . . . . . . . . . . . . . . . Rolling dice - randrange . . . . . . . . . . . . . . . . . . . . . . . Random choice . . . . . . . . . . . . . . . . . . . . . . . . . . . . built-in method . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exception: TypeError: ‘module’ object is not callable . . . . . Fixing the previous code . . . . . . . . . . . . . . . . . . . . . . Exception: AttributeError: module ‘random’ has no attribute Exercise: Number guessing game - level 0 . . . . . . . . . . . . Exercise: Fruit salad . . . . . . . . . . . . . . . . . . . . . . . . . Solution: Number guessing game - level 0 . . . . . . . . . . . . Solution: Fruit salad . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
74 74 74 75 76 76 77 77 77 78 78 79 80 80 80 80
Comparison and Boolean . . . . . . . . . . . . . . . if statement again . . . . . . . . . . . . . . . . . Comparison operators . . . . . . . . . . . . . . . Compare numbers, compare strings . . . . . . Do NOT Compare different types! . . . . . . . Complex if statement with boolean operators Boolean operators . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
82 82 82 82 83 84 85
. . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . .
CONTENTS
Boolean truth tables . . . . . . . . . . . . Boolean values: True and False . . . . . Using True and False in variables . . . . Comparison returns True or False . . . . Assign comparisons to variables . . . . . Flag . . . . . . . . . . . . . . . . . . . . . . Toggle . . . . . . . . . . . . . . . . . . . . . Short circuit . . . . . . . . . . . . . . . . . Short circuit fixed . . . . . . . . . . . . . Does this value count as True or False? True and False values in Python . . . . . Incorrect use of conditions . . . . . . . . Exercise: compare numbers . . . . . . . . Exercise: compare strings . . . . . . . . . Solution: compare numbers . . . . . . . . Solution: compare strings . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
85 86 86 87 87 88 88 89 89 89 90 91 92 92 92 93
Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Single quoted and double quoted strings . . . . . . Long lines . . . . . . . . . . . . . . . . . . . . . . . . Triple quoted strings (multiline) . . . . . . . . . . . String length (len) . . . . . . . . . . . . . . . . . . . String repetition and concatenation . . . . . . . . . A character in a string . . . . . . . . . . . . . . . . . String slice (instead of substr) . . . . . . . . . . . . Change a string . . . . . . . . . . . . . . . . . . . . . How to change a string . . . . . . . . . . . . . . . . String copy . . . . . . . . . . . . . . . . . . . . . . . . String functions and methods (len, upper, lower) . index in string . . . . . . . . . . . . . . . . . . . . . . index in string with range . . . . . . . . . . . . . . rindex in string with range . . . . . . . . . . . . . . find in string . . . . . . . . . . . . . . . . . . . . . . . Find all in the string . . . . . . . . . . . . . . . . . . in string . . . . . . . . . . . . . . . . . . . . . . . . . index if in string . . . . . . . . . . . . . . . . . . . . Encodings: ASCII, Windows-1255, Unicode . . . . raw strings . . . . . . . . . . . . . . . . . . . . . . . . ord . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ord in a file . . . . . . . . . . . . . . . . . . . . . . . chr - number to character . . . . . . . . . . . . . . . Exercise: one string in another string . . . . . . . . Exercise: to ASCII CLI . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
94 94 94 95 96 96 97 97 97 98 98 99 99 100 100 101 101 102 102 102 103 103 104 104 106 107
CONTENTS
Exercise: from ASCII CLI . . . . . . . Solution: one string in another string Solution: compare strings . . . . . . . Solution: to ASCII CLI . . . . . . . . . Solution: from ASCII CLI . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
107 107 107 108 108
Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . Loops: for-in and while . . . . . . . . . . . . . for-in loop on strings . . . . . . . . . . . . . . for-in loop on list . . . . . . . . . . . . . . . . . for-in loop on range . . . . . . . . . . . . . . . Iterable, iterator . . . . . . . . . . . . . . . . . . for in loop with early end using break . . . . for in loop skipping parts using continue . . for in loop with break and continue . . . . . while loop . . . . . . . . . . . . . . . . . . . . . Infinite while loop . . . . . . . . . . . . . . . . While with complex expression . . . . . . . . While with break . . . . . . . . . . . . . . . . . While True . . . . . . . . . . . . . . . . . . . . . Duplicate input call . . . . . . . . . . . . . . . Eliminate duplicate input call . . . . . . . . . do while loop . . . . . . . . . . . . . . . . . . . while with many continue calls . . . . . . . . Break out from multi-level loops . . . . . . . Exit vs return vs break and continue . . . . . Exercise: Print all the locations in a string . . Exercise: Number guessing game . . . . . . . Exercise: Count unique characters . . . . . . Exercise: Convert for-loop to while-loop . . . Solution: Print all the locations in a string . . Solution 1 for Number Guessing . . . . . . . . Solution 2 for Number Guessing (x) . . . . . Solution 3 for Number Guessing (s) . . . . . . Solution for Number Guessing (debug) . . . . Solution for Number Guessing (move) . . . . Solution for Number Guessing (multi-game) Solution: Count unique characters . . . . . . Solution: Convert for-loop to while-loop . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
110 110 110 110 111 111 111 112 112 113 113 114 115 115 116 116 117 117 117 118 118 118 119 119 119 120 121 122 122 123 125 126 127
Formatted printing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 format - sprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Examples using format - indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
CONTENTS
Examples using format with names . . . . . . . . . Format columns . . . . . . . . . . . . . . . . . . . . . Examples using format - alignment . . . . . . . . . Format - string . . . . . . . . . . . . . . . . . . . . . Format characters and types . . . . . . . . . . . . . Format floating point number . . . . . . . . . . . . f-strings (formatted string literals) . . . . . . . . . printf using old %-syntax . . . . . . . . . . . . . . . Format braces, bracket, and parentheses . . . . . . Examples using format with attributes of objects raw f-strings . . . . . . . . . . . . . . . . . . . . . . . Lists . . . . . . . . . . . . . . . . . . . . . . . . . Anything can be a list . . . . . . . . . . . . Any layout . . . . . . . . . . . . . . . . . . . Lists . . . . . . . . . . . . . . . . . . . . . . . List slice with steps . . . . . . . . . . . . . . Change a List . . . . . . . . . . . . . . . . . Change with steps . . . . . . . . . . . . . . List assignment and list copy . . . . . . . . Shallow vs. Deep copy of lists . . . . . . . join . . . . . . . . . . . . . . . . . . . . . . . join list of numbers . . . . . . . . . . . . . . split . . . . . . . . . . . . . . . . . . . . . . . for loop on lists . . . . . . . . . . . . . . . . in list . . . . . . . . . . . . . . . . . . . . . . Where is the element in the list . . . . . . Index improved . . . . . . . . . . . . . . . . [ . . . . . . . . . . . . . . . . . . . . . . . . . [ . . . . . . . . . . . . . . . . . . . . . . . . . [ . . . . . . . . . . . . . . . . . . . . . . . . . Remove element by index [ . . . . . . . . . Remove first element of list . . . . . . . . . Remove several elements of list by index Use list as a queue . . . . . . . . . . . . . . Queue using deque from collections . . . Fixed size queue . . . . . . . . . . . . . . . List as a stack . . . . . . . . . . . . . . . . . stack with deque . . . . . . . . . . . . . . . Exercies: Queue . . . . . . . . . . . . . . . . Exercise: Stack . . . . . . . . . . . . . . . . Exercise: MasterMind . . . . . . . . . . . . Solution: Queue with list . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
129 129 130 130 131 131 132 132 133 133 133
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
135 135 135 136 137 137 138 138 139 139 140 140 141 141 142 142 142 143 143 144 144 145 145 145 146 147 147 148 149 149 150
CONTENTS
Solution: Queue with deque . . . . . . . . . . . . . . . . Solution: Reverse Polish calculator (stack) with lists . . Solution: Reverse Polish calculator (stack) with deque Solution: MasterMind . . . . . . . . . . . . . . . . . . . . MasterMind to debug . . . . . . . . . . . . . . . . . . . . Debugging Queue . . . . . . . . . . . . . . . . . . . . . . sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sort numbers . . . . . . . . . . . . . . . . . . . . . . . . . sort mixed . . . . . . . . . . . . . . . . . . . . . . . . . . . key sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sort with sorted . . . . . . . . . . . . . . . . . . . . . . . . sort vs. sorted . . . . . . . . . . . . . . . . . . . . . . . . . key sort with sorted . . . . . . . . . . . . . . . . . . . . . Sorting characters of a string . . . . . . . . . . . . . . . . range . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Looping over index . . . . . . . . . . . . . . . . . . . . . . Enumerate lists . . . . . . . . . . . . . . . . . . . . . . . . List operators . . . . . . . . . . . . . . . . . . . . . . . . . List of lists . . . . . . . . . . . . . . . . . . . . . . . . . . . List assignment . . . . . . . . . . . . . . . . . . . . . . . . List documentation . . . . . . . . . . . . . . . . . . . . . . tuple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sort tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: color selector menu . . . . . . . . . . . . . . . . Exercise: count digits . . . . . . . . . . . . . . . . . . . . Exercise: Create list . . . . . . . . . . . . . . . . . . . . . Exercise: Count words . . . . . . . . . . . . . . . . . . . . Exercise: Check if number is prime . . . . . . . . . . . . Exercise: DNA sequencing . . . . . . . . . . . . . . . . . Solution: menu . . . . . . . . . . . . . . . . . . . . . . . . Solution: count digits . . . . . . . . . . . . . . . . . . . . Solution: Create list . . . . . . . . . . . . . . . . . . . . . Solution: Count words . . . . . . . . . . . . . . . . . . . . Solution: Check if number is prime . . . . . . . . . . . . Solution: DNA sequencing . . . . . . . . . . . . . . . . . Solution: DNA sequencing with filter . . . . . . . . . . Solution: DNA sequencing with filter and lambda . . . [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . append vs. extend . . . . . . . . . . . . . . . . . . . . . . split and extend . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
150 151 152 153 154 156 157 157 157 158 158 159 159 159 160 160 161 161 162 162 163 163 163 164 165 165 165 166 166 166 167 168 169 170 170 170 171 171 171 172
Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 File types: Text vs Binary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
CONTENTS
Open vs. Read vs. Load . . . . . . . . . . . . . . . Binary files: Images . . . . . . . . . . . . . . . . . Reading an Excel file . . . . . . . . . . . . . . . . . Open and read file (easy but not recommended) Open and read file using with (recommended) . Read file remove newlines . . . . . . . . . . . . . Filename on the command line . . . . . . . . . . Filehandle with return . . . . . . . . . . . . . . . . Read all the lines into a list . . . . . . . . . . . . . Read all the characters into a string (slurp) . . . Not existing file . . . . . . . . . . . . . . . . . . . . Open file exception handling . . . . . . . . . . . . Open many files - exception handling . . . . . . Writing to file . . . . . . . . . . . . . . . . . . . . . Append to file . . . . . . . . . . . . . . . . . . . . . Binary mode . . . . . . . . . . . . . . . . . . . . . . Does file exist? Is it a file? . . . . . . . . . . . . . Direct access of a line in a file . . . . . . . . . . . Exercise: count numbers . . . . . . . . . . . . . . Exercise: strip newlines . . . . . . . . . . . . . . . Exercise: print lines with Report: . . . . . . . . . Exercise: color selector . . . . . . . . . . . . . . . Exercise: ROT13 . . . . . . . . . . . . . . . . . . . . Exercise: Combine lists . . . . . . . . . . . . . . . Solution: count numbers . . . . . . . . . . . . . . Solution: strip newlines . . . . . . . . . . . . . . . Solution: print lines with Report: . . . . . . . . . Solution: color selector . . . . . . . . . . . . . . . Solution: Combine lists . . . . . . . . . . . . . . . Filehandle using with and not using it . . . . . . Dictionary (hash) . . . . . . . . What is a dictionary . . . . When to use dictionaries . Dictionary . . . . . . . . . . keys . . . . . . . . . . . . . . Loop over keys . . . . . . . Loop over dictionary keys Loop using items . . . . . . values . . . . . . . . . . . . . Not existing key . . . . . . Get key . . . . . . . . . . . . Does the key exist? . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
173 174 174 175 175 176 176 176 177 178 178 178 179 180 180 180 181 181 183 184 184 185 185 185 186 186 187 188 188 189
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
190 190 190 190 190 191 191 192 192 193 193 194
CONTENTS
Does the value exist? . . . . . . . . . . . . . . . . . . Delete key . . . . . . . . . . . . . . . . . . . . . . . . List of dictionaries . . . . . . . . . . . . . . . . . . . Shared dictionary . . . . . . . . . . . . . . . . . . . . immutable collection: tuple as dictionary key . . . immutable numbers: numbers as dictionary key . Sort dictionary by value . . . . . . . . . . . . . . . . Sort dictionary keys by value . . . . . . . . . . . . Insertion Order is kept . . . . . . . . . . . . . . . . . Change order of keys in dictionary - OrderedDict Set order of keys in dictionary - OrderedDict . . . Exercise: count characters . . . . . . . . . . . . . . . Exercise: count words . . . . . . . . . . . . . . . . . Exercise: count words from a file . . . . . . . . . . Exercise: Apache log . . . . . . . . . . . . . . . . . . Exercise: Combine lists again . . . . . . . . . . . . Exercise: counting DNA bases . . . . . . . . . . . . Exercise: Count Amino Acids . . . . . . . . . . . . Exercise: List of dictionaries . . . . . . . . . . . . . Exercise: Dictinoary of dictionaries . . . . . . . . . Exercise: Age limit with dictionaries . . . . . . . . Solution: count characters . . . . . . . . . . . . . . Default Dict . . . . . . . . . . . . . . . . . . . . . . . Solution: count characters with default dict . . . . Solution: count words . . . . . . . . . . . . . . . . . Solution: count words in file . . . . . . . . . . . . . Solution: Apache log . . . . . . . . . . . . . . . . . . Solution: Combine lists again . . . . . . . . . . . . Solution: counting DNA bases . . . . . . . . . . . . Solution: Count Amino Acids . . . . . . . . . . . . Do not change dictionary in loop . . . . . . . . . . Sets . . . . . . . . . . . . . . . . . . . . . . . . . . sets . . . . . . . . . . . . . . . . . . . . . . . set operations . . . . . . . . . . . . . . . . . Creating a set . . . . . . . . . . . . . . . . . Creating an empty set . . . . . . . . . . . . Adding an element to a set (add) . . . . . Merging one set into another set (update) set intersection . . . . . . . . . . . . . . . . set subset . . . . . . . . . . . . . . . . . . . . set symmetric difference . . . . . . . . . . set union . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
195 195 196 196 197 198 198 199 201 201 202 202 203 203 204 205 205 205 206 206 207 207 208 209 210 211 211 212 212 213 214
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
216 216 216 217 217 217 218 218 219 220 220
CONTENTS
set relative complement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Functions (subroutines) . . . . . . . . . . . . . . . . . . . . . . . Why use functions? . . . . . . . . . . . . . . . . . . . . . . . Defining simple function . . . . . . . . . . . . . . . . . . . . Passing positional parameters to a function . . . . . . . . . Function parameters can be named . . . . . . . . . . . . . . Mixing positional and named parameters . . . . . . . . . . Default values, optional parameters, optional parameters Default value in first param . . . . . . . . . . . . . . . . . . Several defaults, using names . . . . . . . . . . . . . . . . . Arbitrary number of arguments * . . . . . . . . . . . . . . . Fixed parmeters before the others . . . . . . . . . . . . . . . Arbitrary key-value pairs in parameters ** . . . . . . . . . Extra key-value pairs in parameters . . . . . . . . . . . . . Every parameter option . . . . . . . . . . . . . . . . . . . . . Duplicate declaration of functions (multiple signatures) . Pylint duplicate declaration . . . . . . . . . . . . . . . . . . Return more than one value . . . . . . . . . . . . . . . . . . Recursive factorial . . . . . . . . . . . . . . . . . . . . . . . . Recursive Fibonacci . . . . . . . . . . . . . . . . . . . . . . . Non-recursive Fibonacci . . . . . . . . . . . . . . . . . . . . Unbound recursion . . . . . . . . . . . . . . . . . . . . . . . . Variable assignment and change - Immutable . . . . . . . . Variable assignment and change - Mutable . . . . . . . . . Parameter passing of functions . . . . . . . . . . . . . . . . Passing references . . . . . . . . . . . . . . . . . . . . . . . . Function documentation . . . . . . . . . . . . . . . . . . . . Sum ARGV . . . . . . . . . . . . . . . . . . . . . . . . . . . . Copy-paste code . . . . . . . . . . . . . . . . . . . . . . . . . Copy-paste code fixed . . . . . . . . . . . . . . . . . . . . . . Copy-paste code further improvement . . . . . . . . . . . . Palindrome . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: statistics . . . . . . . . . . . . . . . . . . . . . . . . Exercise: recursive . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Tower of Hanoi . . . . . . . . . . . . . . . . . . . . Exercise: Merge and Bubble sort . . . . . . . . . . . . . . . . Exercise: Refactor previous solutions to use functions . . . Solution: statistics . . . . . . . . . . . . . . . . . . . . . . . . Solution: recursive . . . . . . . . . . . . . . . . . . . . . . . . Solution: Tower of Hanoi . . . . . . . . . . . . . . . . . . . . Solution: Merge and Bubble sort . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
223 223 223 224 224 225 226 227 227 228 229 230 231 231 231 232 232 233 233 234 234 235 236 236 236 237 238 238 239 239 240 240 241 241 242 242 242 243 243 244
CONTENTS
Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Before modules . . . . . . . . . . . . . . . . . . . . . . . Create modules . . . . . . . . . . . . . . . . . . . . . . . path to load modules from - The module search path sys.path - the module search path . . . . . . . . . . . . Flat project directory structure . . . . . . . . . . . . . . Absolute path . . . . . . . . . . . . . . . . . . . . . . . . Relative path . . . . . . . . . . . . . . . . . . . . . . . . Python modules are compiled . . . . . . . . . . . . . . How “import” and “from” work? . . . . . . . . . . . . Runtime loading of modules . . . . . . . . . . . . . . . Conditional loading of modules . . . . . . . . . . . . . Duplicate importing of functions . . . . . . . . . . . . Script or library . . . . . . . . . . . . . . . . . . . . . . . Script or library - import . . . . . . . . . . . . . . . . . Script or library - from import . . . . . . . . . . . . . . assert to verify values . . . . . . . . . . . . . . . . . . . mycalc as a self testing module . . . . . . . . . . . . . doctest . . . . . . . . . . . . . . . . . . . . . . . . . . . . Scope of import . . . . . . . . . . . . . . . . . . . . . . . Export import . . . . . . . . . . . . . . . . . . . . . . . . Export import with all . . . . . . . . . . . . . . . . . . . import module . . . . . . . . . . . . . . . . . . . . . . . Execute at import time . . . . . . . . . . . . . . . . . . Import multiple times . . . . . . . . . . . . . . . . . . . Exercise: Number guessing . . . . . . . . . . . . . . . . Exercies: Scripts and modules . . . . . . . . . . . . . . Exercise: Module my_sum . . . . . . . . . . . . . . . . Exercise: Convert your script to module . . . . . . . . Exercise: Add doctests to your own code . . . . . . . Solution: Module my_sum . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
246 246 246 247 247 247 248 248 249 249 249 250 250 251 251 252 252 253 254 255 256 257 258 258 258 259 259 259 260 260 260
Regular Expressions . . . . . . . . . . . . . . . . . . What are Regular Expressions (aka. Regexes)? What are Regular Expressions good for? . . . . Examples . . . . . . . . . . . . . . . . . . . . . . . Where can I use it ? . . . . . . . . . . . . . . . . grep . . . . . . . . . . . . . . . . . . . . . . . . . . Regexes first match . . . . . . . . . . . . . . . . . Match numbers . . . . . . . . . . . . . . . . . . . Capture . . . . . . . . . . . . . . . . . . . . . . . . Capture more . . . . . . . . . . . . . . . . . . . . Capture even more . . . . . . . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
262 262 262 262 263 263 264 264 265 265 266
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
CONTENTS
findall . . . . . . . . . . . . . . . . . . . . . . . . findall with capture . . . . . . . . . . . . . . . findall with capture more than one . . . . . . Any Character . . . . . . . . . . . . . . . . . . Match dot . . . . . . . . . . . . . . . . . . . . . Character classes . . . . . . . . . . . . . . . . . Common characer classes . . . . . . . . . . . . Negated character class . . . . . . . . . . . . . Optional character . . . . . . . . . . . . . . . . Regex 0 or more quantifier . . . . . . . . . . . Quantifiers . . . . . . . . . . . . . . . . . . . . . Quantifiers limit . . . . . . . . . . . . . . . . . Quantifiers on character classes . . . . . . . . Greedy quantifiers . . . . . . . . . . . . . . . . Minimal quantifiers . . . . . . . . . . . . . . . Anchors . . . . . . . . . . . . . . . . . . . . . . Anchors on both end . . . . . . . . . . . . . . . Match ISBN numbers . . . . . . . . . . . . . . Matching a section . . . . . . . . . . . . . . . . Matching a section - minimal . . . . . . . . . Matching a section negated character class . DOTALL S (single line) . . . . . . . . . . . . . MULTILINE M . . . . . . . . . . . . . . . . . . Two regex with logical or . . . . . . . . . . . . Alternatives . . . . . . . . . . . . . . . . . . . . Grouping and Alternatives . . . . . . . . . . . Internal variables . . . . . . . . . . . . . . . . . More internal variables . . . . . . . . . . . . . Regex DNA . . . . . . . . . . . . . . . . . . . . Regex IGNORECASE . . . . . . . . . . . . . . Regex VERBOSE X . . . . . . . . . . . . . . . . Substitution . . . . . . . . . . . . . . . . . . . . findall capture . . . . . . . . . . . . . . . . . . . Fixing dates . . . . . . . . . . . . . . . . . . . . Duplicate numbers . . . . . . . . . . . . . . . . Remove spaces . . . . . . . . . . . . . . . . . . Replace string in assembly code . . . . . . . . Full example of previous . . . . . . . . . . . . Split with regex . . . . . . . . . . . . . . . . . . Exercises: Regexes part 1 . . . . . . . . . . . . Exercise: Regexes part 2 . . . . . . . . . . . . . Exercise: Sort SNMP numbers . . . . . . . . . Exercise: parse hours log file and give report
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
266 267 267 268 269 269 270 270 270 271 271 271 272 273 273 274 275 276 277 277 277 277 278 279 280 280 280 281 281 282 282 283 284 284 285 286 286 289 290 290 291 292 293
CONTENTS
Exercise: Parse ini file . . . . . . . . . . . . . . Exercise: Replace Python . . . . . . . . . . . . Exercise: Extract phone numbers . . . . . . . Solution: Sort SNMP numbers . . . . . . . . . Solution: parse hours log file and give report Solution: Processing INI file manually . . . . Solution: Processing config file . . . . . . . . Solution: Extract phone numbers . . . . . . . Regular Expressions Cheat sheet . . . . . . . Fix bad JSON . . . . . . . . . . . . . . . . . . . Fix very bad JSON . . . . . . . . . . . . . . . . Raw string or escape . . . . . . . . . . . . . . . Remove spaces regex . . . . . . . . . . . . . . . Regex Unicode . . . . . . . . . . . . . . . . . . Anchors Other example . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
294 295 295 296 297 299 300 301 301 302 303 304 305 305 306
PyCharm . . . . . . . . . . . . . . . . . . . . . . . . PyCharm Intro . . . . . . . . . . . . . . . . . . PyCharm configurations . . . . . . . . . . . . PyCharm Project . . . . . . . . . . . . . . . . . PyCharm Files . . . . . . . . . . . . . . . . . . . PyCharm - run code . . . . . . . . . . . . . . . PyCharm Python console at the bottom left . Refactoring example with PyCharm . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
308 308 308 308 308 308 308 309
Python standard modules . . . . . . . . . . . . . . . . . . . . . . Some Standard modules . . . . . . . . . . . . . . . . . . . . . sys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Writing to standard error (stderr) . . . . . . . . . . . . . . . Current directory (getcwd, pwd, chdir) . . . . . . . . . . . . OS dir (mkdir, makedirs, remove, rmdir) . . . . . . . . . . . python which OS are we running on (os, platform) . . . . Get process ID . . . . . . . . . . . . . . . . . . . . . . . . . . OS path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Traverse directory tree - list directories recursively . . . . os.path.join . . . . . . . . . . . . . . . . . . . . . . . . . . . . Directory listing . . . . . . . . . . . . . . . . . . . . . . . . . expanduser - handle tilde ∼ . . . . . . . . . . . . . . . . . . Listing specific files using glob . . . . . . . . . . . . . . . . . External command with system . . . . . . . . . . . . . . . . subprocess . . . . . . . . . . . . . . . . . . . . . . . . . . . . . subprocess in the background . . . . . . . . . . . . . . . . . Accessing the system environment variables from Python
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
310 310 310 311 312 312 312 313 313 313 314 314 314 315 315 315 316 317
CONTENTS
Set env and run command . . . . . . . . . . . shutil . . . . . . . . . . . . . . . . . . . . . . . . time . . . . . . . . . . . . . . . . . . . . . . . . . sleep in Python . . . . . . . . . . . . . . . . . . timer . . . . . . . . . . . . . . . . . . . . . . . . Current date and time datetime now . . . . . Converting string to datetime . . . . . . . . . datetime arithmeticis . . . . . . . . . . . . . . Rounding datetime object to nearest second Signals and Python . . . . . . . . . . . . . . . . Sending Signal . . . . . . . . . . . . . . . . . . Catching Signal . . . . . . . . . . . . . . . . . . Catching Ctrl-C on Unix . . . . . . . . . . . . Catching Ctrl-C on Unix confirm . . . . . . . Alarm signal and timeouts . . . . . . . . . . . deep copy list . . . . . . . . . . . . . . . . . . . deep copy dictionary . . . . . . . . . . . . . . . Exercise: Catching Ctrl-C on Unix 2nd time Exercise: Signals . . . . . . . . . . . . . . . . . Ctrl-z . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
318 318 319 319 320 321 321 322 322 322 322 323 323 324 324 325 327 328 329 329
JSON . . . . . . . . . . . . . . . . . . . . . . . . JSON - JavaScript Object Notation . . . dumps . . . . . . . . . . . . . . . . . . . . loads . . . . . . . . . . . . . . . . . . . . . dump . . . . . . . . . . . . . . . . . . . . . load . . . . . . . . . . . . . . . . . . . . . . Round trip . . . . . . . . . . . . . . . . . . Pretty print JSON . . . . . . . . . . . . . . Sort keys in JSON . . . . . . . . . . . . . . Set order of keys in JSON - OrderedDict Exercise: Counter in JSON . . . . . . . . Exercise: Phone book . . . . . . . . . . . Exercise: Processes . . . . . . . . . . . . . Solution: Counter in JSON . . . . . . . . Solution: Phone book . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
330 330 330 331 331 332 332 333 334 335 336 336 337 337 338
Command line arguments with argparse Modules to handle the command line argparse . . . . . . . . . . . . . . . . . . Basic usage of argparse . . . . . . . . . Positional argument . . . . . . . . . . . Many positional argument . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
340 340 340 341 342 343
. . . . . .
CONTENTS
Convert to integers . . . . . . . . . . . . . . . . . . . . . . . Convert to integer . . . . . . . . . . . . . . . . . . . . . . . Named arguments . . . . . . . . . . . . . . . . . . . . . . . Boolean Flags . . . . . . . . . . . . . . . . . . . . . . . . . . Short names . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Command line parameters . . . . . . . . . . . . Exercise: argparse positional and named . . . . . . . . . . argparse print help explicitely . . . . . . . . . . . . . . . . Argparse xor - mutual exlucise - only one - exactly one
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
343 344 344 345 346 346 346 346 347
Exception handling . . . . . . . . . . . . . . . . . . . Hierarchy of calls . . . . . . . . . . . . . . . . . . Handling errors as return values . . . . . . . . Handling errors as exceptions . . . . . . . . . . A simple exception . . . . . . . . . . . . . . . . . Working on a list . . . . . . . . . . . . . . . . . . Catch ZeroDivisionError exception . . . . . . . Module to open files and calculate something File for exception handling example . . . . . . Open files - exception . . . . . . . . . . . . . . . Handle divide by zero exception . . . . . . . . . Handle files - exception . . . . . . . . . . . . . . Catch all the exceptions and show their type . List exception types . . . . . . . . . . . . . . . . Exceptions . . . . . . . . . . . . . . . . . . . . . . How to raise an exception . . . . . . . . . . . . Stack trace . . . . . . . . . . . . . . . . . . . . . . Exercies: Exception int conversion . . . . . . . Exercies: Raise Exception . . . . . . . . . . . . . Solution: Exception int conversion (specific) . Solution: Exception int conversion (all other) . Solution: Raise Exception . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
349 349 349 350 350 351 352 353 353 354 355 355 356 357 358 358 359 360 361 361 362 363
Classes - OOP - Object Oriented Programming . Why Object Oriented Programming? . . . . . . Generic Object Oriented Programming terms . OOP in Python . . . . . . . . . . . . . . . . . . . OOP in Python (numbers, strings, lists) . . . . OOP in Python (argparse) . . . . . . . . . . . . . Create a class . . . . . . . . . . . . . . . . . . . . Import module containing class . . . . . . . . . Import class from module . . . . . . . . . . . . . Initialize a class - constructor, attributes . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
364 364 364 364 364 365 365 366 366 367
CONTENTS
Attributes are not special . . . . . . . . . . . . . . . Create Point class . . . . . . . . . . . . . . . . . . . . Initialize a class - constructor, attributes . . . . . . Methods . . . . . . . . . . . . . . . . . . . . . . . . . Stringify class . . . . . . . . . . . . . . . . . . . . . . Inheritance . . . . . . . . . . . . . . . . . . . . . . . . Inheritance - another level . . . . . . . . . . . . . . Modes of method inheritance . . . . . . . . . . . . Modes of method inheritance - implicit . . . . . . Modes of method inheritance - override . . . . . . Modes of method inheritance - extend . . . . . . . Modes of method inheritance - delegate - provide Composition - Line . . . . . . . . . . . . . . . . . . . Some comments . . . . . . . . . . . . . . . . . . . . Class in function . . . . . . . . . . . . . . . . . . . . Serialization of instances with pickle . . . . . . . . Quick Class definition and usage . . . . . . . . . . Exercise: Add move_rad to based on radians . . . Exercise: Improve previous examples . . . . . . . . Exercise: Polygon . . . . . . . . . . . . . . . . . . . . Exercise: Number . . . . . . . . . . . . . . . . . . . . Exercise: Library . . . . . . . . . . . . . . . . . . . . Exercise: Bookexchange . . . . . . . . . . . . . . . . Exercise: Represent turtle graphics . . . . . . . . . Solution - Polygon . . . . . . . . . . . . . . . . . . . PyPi - Python Package Index What is PyPi? . . . . . . . . Easy Install . . . . . . . . . pip . . . . . . . . . . . . . . . Upgrade pip . . . . . . . . . PYTHONPATH . . . . . . . Virtualenv . . . . . . . . . . Virtualenv for Python 3 . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
367 368 368 368 369 370 371 372 372 372 373 374 374 375 375 375 376 376 377 377 378 378 378 378 378
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
380 380 380 380 380 380 380 381
SQLite Database Access . . . . . . . . . . SQLite . . . . . . . . . . . . . . . . . . Connecting to SQLite database . . . Create TABLE in SQLite . . . . . . . INSERT data into SQLite database . SELECT data from SQLite database . A counter . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
382 382 382 382 383 384 384
MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
CONTENTS
Install MySQL support . . . . . . . . . . . . Create database user (manually) . . . . . . Create database (manually) . . . . . . . . . Create table (manually) . . . . . . . . . . . Connect to MySQL . . . . . . . . . . . . . . Connect to MySQL and Handle exception Select data . . . . . . . . . . . . . . . . . . . Select more data . . . . . . . . . . . . . . . Select all data fetchall . . . . . . . . . . . . Select some data fetchmany . . . . . . . . Select some data WHERE clause . . . . . Select into dictionaries . . . . . . . . . . . . Insert data . . . . . . . . . . . . . . . . . . . Update data . . . . . . . . . . . . . . . . . . Delete data . . . . . . . . . . . . . . . . . . . Exercise MySQL . . . . . . . . . . . . . . . Exercise: MySQL Connection . . . . . . . Solution: MySQL Connection . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
387 387 387 388 388 389 389 390 391 391 392 393 394 394 395 396 396 396
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
398 398 398 398 398 399 400 400
SQLAlchemy . . . . . . . . . . . . . . . . . . . . . . . . . . SQLAlchemy hierarchy . . . . . . . . . . . . . . . . . SQLAlchemy engine . . . . . . . . . . . . . . . . . . . SQLAlchemy autocommit . . . . . . . . . . . . . . . SQLAlchemy engine CREATE TABLE . . . . . . . . SQLAlchemy engine INSERT . . . . . . . . . . . . . SQLAlchemy engine SELECT . . . . . . . . . . . . . SQLAlchemy engine SELECT all . . . . . . . . . . . SQLAlchemy engine SELECT fetchall . . . . . . . . SQLAlchemy engine SELECT aggregate . . . . . . . SQLAlchemy engine SELECT IN . . . . . . . . . . . SQLAlchemy engine SELECT IN with placeholders SQLAlchemy engine connection . . . . . . . . . . . . SQLAlchemy engine transaction . . . . . . . . . . . SQLAlchemy engine using context managers . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
402 402 402 402 402 403 403 404 404 405 405 406 406 406 408
PostgreSQL . . . . . . . . . . . . . . PostgreSQL install . . . . . . . Python and Postgresql . . . . . PostgreSQL connect . . . . . . INSERT . . . . . . . . . . . . . . INSERT (from command line) SELECT . . . . . . . . . . . . . DELETE . . . . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
CONTENTS
Exercise: Create table . . . . . . . . . . . . . . . . . SQLAlchemy Metada . . . . . . . . . . . . . . . . . SQLAlchemy types . . . . . . . . . . . . . . . . . . . SQLAlchemy ORM - Object Relational Mapping . SQLAlchemy ORM create . . . . . . . . . . . . . . . SQLAlchemy ORM schema . . . . . . . . . . . . . . SQLAlchemy ORM reflection . . . . . . . . . . . . SQLAlchemy ORM INSERT after automap . . . . SQLAlchemy ORM INSERT . . . . . . . . . . . . . SQLAlchemy ORM SELECT . . . . . . . . . . . . . SQLAlchemy ORM SELECT cross tables . . . . . . SQLAlchemy ORM SELECT and INSERT . . . . . SQLAlchemy ORM UPDATE . . . . . . . . . . . . SQLAlchemy ORM logging . . . . . . . . . . . . . . Solution: Create table . . . . . . . . . . . . . . . . . Exercise: Inspector . . . . . . . . . . . . . . . . . . . SQLAlchemy CREATE and DROP . . . . . . . . . SQLAlchemy Notes . . . . . . . . . . . . . . . . . . SQLAlchemy Meta SQLite CREATE . . . . . . . . SQLAlchemy Meta Reflection . . . . . . . . . . . . SQLAlchemy Meta INSERT . . . . . . . . . . . . . SQLAlchemy Meta SELECT . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
408 408 410 411 411 412 413 413 414 414 415 415 416 417 417 418 419 420 420 421 421 421
NoSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 Types of NoSQL databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 MongoDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MongoDB CRUD . . . . . . . . . . . . . . . . . . . . . . . . . . Install MongoDB support . . . . . . . . . . . . . . . . . . . . . Python MongoDB insert . . . . . . . . . . . . . . . . . . . . . MongoDB CLI . . . . . . . . . . . . . . . . . . . . . . . . . . . . Python MongoDB find . . . . . . . . . . . . . . . . . . . . . . Python MongoDB find refine . . . . . . . . . . . . . . . . . . Python MongoDB update . . . . . . . . . . . . . . . . . . . . . Python MongoDB remove (delete) . . . . . . . . . . . . . . . Python MongoDB replace . . . . . . . . . . . . . . . . . . . . . Python MongoDB upsert . . . . . . . . . . . . . . . . . . . . . Python Mongodb: TypeError: upsert must be True or False
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
423 423 423 423 424 425 425 426 426 426 427 428
Redis . . . . . . . . Redis CLI . . . Redis list keys Redis set get . Redis incr . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
430 430 430 430 431
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
CONTENTS
Redis incrby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431 Redis setex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431 Web client . . . . . . . . . . . . . . . . . . . . . . . urllib the web client . . . . . . . . . . . . . . . urllib2 the web client . . . . . . . . . . . . . . httpbin.org . . . . . . . . . . . . . . . . . . . . . requests get . . . . . . . . . . . . . . . . . . . . Download image using requests . . . . . . . . Download image as a stream using requests Download zip file . . . . . . . . . . . . . . . . . Extract zip file . . . . . . . . . . . . . . . . . . . Interactive Requests . . . . . . . . . . . . . . . requests get JSON . . . . . . . . . . . . . . . . requests get JSON UserAgent . . . . . . . . . . requests get JSON UserAgent . . . . . . . . . . requests get header . . . . . . . . . . . . . . . . requests change header . . . . . . . . . . . . . requests post . . . . . . . . . . . . . . . . . . . . Tweet . . . . . . . . . . . . . . . . . . . . . . . . API config file . . . . . . . . . . . . . . . . . . . bit.ly . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Combine web server and client . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
433 433 433 434 434 434 434 435 435 435 436 436 436 437 437 438 438 439 439 440
Python Web server . . . . . . . . . Hello world web . . . . . . . . Dump web environment info . Web echo . . . . . . . . . . . . . Web form . . . . . . . . . . . . Resources . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
441 441 441 442 443 444
Python Flask . . . . . . . . . . . . . . . . Python Flask intro . . . . . . . . . . Python Flask installation . . . . . . Flask: Hello World . . . . . . . . . . Flask: Run Hello World . . . . . . . Flask: testing hello world . . . . . . Flask generated page - time . . . . . Flask generated page - time tested . Flask: Echo GET . . . . . . . . . . . Flask: Echo POST . . . . . . . . . . . Flask: templates . . . . . . . . . . . . Flask: templates . . . . . . . . . . . . Flask: templates with parameters .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
445 445 445 445 446 447 448 449 450 451 453 453 454
CONTENTS
Flask: runner . . . . . . . . . . . . . . . . . . . . . Exercise: Flask calculator . . . . . . . . . . . . . . Static files . . . . . . . . . . . . . . . . . . . . . . . Flask Logging . . . . . . . . . . . . . . . . . . . . . Flask: Counter . . . . . . . . . . . . . . . . . . . . . Color selector without session . . . . . . . . . . . Session management . . . . . . . . . . . . . . . . . Flask custom 404 page . . . . . . . . . . . . . . . . Flask Error page . . . . . . . . . . . . . . . . . . . Flask URL routing . . . . . . . . . . . . . . . . . . Flask Path params . . . . . . . . . . . . . . . . . . Flask Path params (int) . . . . . . . . . . . . . . . Flask Path params add (int) . . . . . . . . . . . . . Flask Path params add (path) . . . . . . . . . . . . Jinja loop, conditional, include . . . . . . . . . . . Exercise: Flask persistent . . . . . . . . . . . . . . Exercise: Flask persistent . . . . . . . . . . . . . . Flask Exercises . . . . . . . . . . . . . . . . . . . . Flask login . . . . . . . . . . . . . . . . . . . . . . . Flask JSON API . . . . . . . . . . . . . . . . . . . . Flask and AJAX . . . . . . . . . . . . . . . . . . . . Flask and AJAX . . . . . . . . . . . . . . . . . . . . passlib . . . . . . . . . . . . . . . . . . . . . . . . . Flask Testing . . . . . . . . . . . . . . . . . . . . . . Flask Deploy app . . . . . . . . . . . . . . . . . . . Flask Simple Authentication + test . . . . . . . . Flask REST API . . . . . . . . . . . . . . . . . . . . Flask REST API - Echo . . . . . . . . . . . . . . . Flask REST API - parameters in path . . . . . . . Flask REST API - parameter parsing . . . . . . . Flask REST API - parameter parsing - required . Networking . . . . . . . . . Secure shell . . . . . . ssh . . . . . . . . . . . . ssh from Windows . . Parallel ssh . . . . . . . telnet . . . . . . . . . . prompt for password . Python nmap . . . . . ftp . . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
455 455 455 456 457 457 458 458 459 460 461 461 462 462 463 464 464 465 465 466 467 470 472 472 474 475 476 476 477 478 479
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
481 481 481 481 482 482 483 483 484
Interactive shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
CONTENTS
The Python interactive shell . . . REPL - Read Evaluate Print Loop Using Modules . . . . . . . . . . . Getting help . . . . . . . . . . . . . Exercise: Interactive shell . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
486 486 487 488 489
Testing Demo . . . . . . . . . . . . . . . . . . . . . . How do you test your code? . . . . . . . . . . . What is testing? . . . . . . . . . . . . . . . . . . . What is testing really? . . . . . . . . . . . . . . . Testing demo tools . . . . . . . . . . . . . . . . . Testing demo methodology . . . . . . . . . . . . Testing demo - AUT - Application Under Test Testing demo - use the module . . . . . . . . . . Testing demo: doctest . . . . . . . . . . . . . . . Testing demo: doctest with failure . . . . . . . Testing demo: Unittest success . . . . . . . . . . Testing demo: Unittest failure . . . . . . . . . . Testing demo: pytest using classes . . . . . . . . Testing demo: pytest using classes - failure . . Testing demo: pytest without classes . . . . . . Testing demo: pytest run doctests . . . . . . . . Testing demo: pytest run unittest . . . . . . . . Exercise: Testing demo . . . . . . . . . . . . . . Solution: Testing demo . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
490 490 490 491 491 491 492 492 493 494 496 497 498 499 501 502 502 502 503
Types in Python . . . . . . . . . . . mypy . . . . . . . . . . . . . . . Types of variables . . . . . . . Types of function parameters Types used properly . . . . . . TODO: mypy . . . . . . . . . .
. . . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
504 504 504 504 505 505
Testing Intro . . . . . . . . . . . . . . . . . . The software testing equasion . . . . . The software testing equasion (fixed) . The pieces of your software? . . . . . . Manual testing . . . . . . . . . . . . . . What to tests? . . . . . . . . . . . . . . . Continuous Integration . . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
506 506 506 506 506 506 507
Functional programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508 Functional programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508 Iterators (Iterables) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
CONTENTS
range . . . . . . . . . . . . . . . . . . . . . . . . range with list . . . . . . . . . . . . . . . . . . . range vs. list size . . . . . . . . . . . . . . . . . for loop with transformation . . . . . . . . . . map . . . . . . . . . . . . . . . . . . . . . . . . . map delaying function call . . . . . . . . . . . map on many values . . . . . . . . . . . . . . . map with list . . . . . . . . . . . . . . . . . . . double with lambda . . . . . . . . . . . . . . . What is lambda in Python? . . . . . . . . . . . lambda returning tuple . . . . . . . . . . . . . map returning tuples . . . . . . . . . . . . . . . lambda with two parameters . . . . . . . . . . map for more than one iterable . . . . . . . . map on uneven lists . . . . . . . . . . . . . . . replace None (for Python 2) . . . . . . . . . . map on uneven lists - fixed (for Python 2) . . map mixed iterators . . . . . . . . . . . . . . . map fetch value from dict . . . . . . . . . . . . Exercise: string to length . . . . . . . . . . . . Exercise: row to length . . . . . . . . . . . . . Exercise: compare rows . . . . . . . . . . . . . Solution: string to length . . . . . . . . . . . . Solution: row to length . . . . . . . . . . . . . Solution: compare rows . . . . . . . . . . . . . filter . . . . . . . . . . . . . . . . . . . . . . . . . filter with lambda . . . . . . . . . . . . . . . . filter - map example . . . . . . . . . . . . . . . filter - map in one expression . . . . . . . . . Get indexes of values . . . . . . . . . . . . . . reduce . . . . . . . . . . . . . . . . . . . . . . . . reduce with default . . . . . . . . . . . . . . . . zip . . . . . . . . . . . . . . . . . . . . . . . . . . Creating dictionary from two lists using zip all, any . . . . . . . . . . . . . . . . . . . . . . . Compare elements of list with scalar . . . . . List comprehension - double . . . . . . . . . . List comprehension - simple expression . . . List generator . . . . . . . . . . . . . . . . . . . List comprehension . . . . . . . . . . . . . . . Dict comprehension . . . . . . . . . . . . . . . Lookup table with lambda . . . . . . . . . . . Read lines without newlines . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
509 511 512 513 514 516 517 518 519 520 521 521 522 522 522 523 523 524 524 525 525 525 525 525 526 526 527 527 528 529 530 531 532 532 533 533 534 534 535 536 537 537 537
CONTENTS
Read key-value pairs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Create index-to-value mapping in a dictionary based on a list of values Exercise: min, max, factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Prime numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Many validator functions . . . . . . . . . . . . . . . . . . . . . . . Exercise: Calculator using lookup table . . . . . . . . . . . . . . . . . . . . Exercise: parse file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Solution: min, max, factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . Solution: Prime numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Solution: Many validator functions . . . . . . . . . . . . . . . . . . . . . . . Solution: Calculator using lookup table . . . . . . . . . . . . . . . . . . . . map with condtion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . map with lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . map with lambda with condition . . . . . . . . . . . . . . . . . . . . . . . . List comprehension - complex . . . . . . . . . . . . . . . . . . . . . . . . . . Iterators - with and without Itertools . . . . . . . . . . . Advantages of iterators and generators . . . . . . . . The Fibonacci research institute . . . . . . . . . . . . . Fibonacci plain . . . . . . . . . . . . . . . . . . . . . . . Fibonacci copy-paste . . . . . . . . . . . . . . . . . . . . Iterators Glossary . . . . . . . . . . . . . . . . . . . . . . What are iterators and iterables? . . . . . . . . . . . . A file-handle is an iterator . . . . . . . . . . . . . . . . range is iterable but it is not an iterator . . . . . . . . Iterator: a counter . . . . . . . . . . . . . . . . . . . . . Using iterator . . . . . . . . . . . . . . . . . . . . . . . . Iterator without temporary variable . . . . . . . . . . The type of the iterator . . . . . . . . . . . . . . . . . . Using iterator with next . . . . . . . . . . . . . . . . . . Mixing for and next . . . . . . . . . . . . . . . . . . . . Iterable which is not an iterator . . . . . . . . . . . . . Iterator returning multiple values . . . . . . . . . . . . Range-like iterator . . . . . . . . . . . . . . . . . . . . . Unbound or infinite iterator . . . . . . . . . . . . . . . Unbound iterator Fibonacci . . . . . . . . . . . . . . . Operations on Unbound iterator . . . . . . . . . . . . . itertools . . . . . . . . . . . . . . . . . . . . . . . . . . . . itertools - count . . . . . . . . . . . . . . . . . . . . . . . itertools - cycle . . . . . . . . . . . . . . . . . . . . . . . Exercise: iterators - reimplement the range function Exercise: iterators - cycle . . . . . . . . . . . . . . . . . Exercise: iterators - alter . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
538 538 539 539 539 540 540 541 542 542 542 543 543 544 544
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
545 545 545 545 545 546 546 548 548 550 550 551 551 552 552 553 554 554 555 556 558 558 559 559 560 560 560
CONTENTS
Exercise: iterators - limit Fibonacci . . . . . Exercise: iterators - Fibonacci less memory Exercise: read char . . . . . . . . . . . . . . . Exercise: read section . . . . . . . . . . . . . Exercise: collect packets . . . . . . . . . . . . Exercise: compare files . . . . . . . . . . . . Solution: iterators - limit Fibonacci . . . . . Solution: iterators - Fibonacci less memory Solution: read section . . . . . . . . . . . . . Solution: compare files . . . . . . . . . . . . Solution: collect packets . . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
561 561 561 561 562 563 564 565 565 566 567
Generators and Generator Expressions . . . . . . . . . . . . . . . . Generators Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . Iterators vs Generators . . . . . . . . . . . . . . . . . . . . . . . . List comprehension and Generator Expression . . . . . . . . . . List comprehension vs Generator Expression - less memory . . List comprehension vs Generator Expression - lazy evaluation Generator: function with yield - call next . . . . . . . . . . . . . Generators - call next . . . . . . . . . . . . . . . . . . . . . . . . . Generator with yield . . . . . . . . . . . . . . . . . . . . . . . . . . Generators - fixed counter . . . . . . . . . . . . . . . . . . . . . . Generators - counter . . . . . . . . . . . . . . . . . . . . . . . . . . Generators - counter with parameter . . . . . . . . . . . . . . . . Generators - my_range . . . . . . . . . . . . . . . . . . . . . . . . Fibonacci - generator . . . . . . . . . . . . . . . . . . . . . . . . . Infinite series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Integers + 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Integers + Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . Filtered Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . . . . The series.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . generator - unbound count (with yield) . . . . . . . . . . . . . . iterator - cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Alternator . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Prime number generator . . . . . . . . . . . . . . . . . Exercise: generator . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Tower of Hanoi . . . . . . . . . . . . . . . . . . . . . . . Exercise: Binary file reader . . . . . . . . . . . . . . . . . . . . . . Exercise: File reader with records . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
570 570 570 570 571 573 574 575 575 576 576 577 578 579 579 579 580 580 581 582 583 583 584 584 584 585 585 585
Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587 Simple logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587
CONTENTS
Simple logging - set level . . . . . . Simple logging to a file . . . . . . . Simple logging format . . . . . . . . Simple logging change date format getLogger . . . . . . . . . . . . . . . . Time-based logrotation . . . . . . . Size-based logrotation . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
587 588 588 588 589 590 590
Closures . . . . . . . . . . . . . . . . . . . . Counter local - not working . . . . . Counter with global . . . . . . . . . . Create incrementors . . . . . . . . . . Create internal function . . . . . . . . Create function by a function . . . . Create function with parameters . . Counter closure . . . . . . . . . . . . . Make incrementor with def (closure) Make incrementor with lambda . . . Exercise: closure bank . . . . . . . . . Solution: closure bank . . . . . . . . . Solution: counter with parameter . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
592 592 592 593 593 594 594 595 596 596 597 597 598
Decorators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Function assignment . . . . . . . . . . . . . . . . . . . . . . Function inside other function . . . . . . . . . . . . . . . . Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . Use cases for decorators in Python . . . . . . . . . . . . . A recursive Fibonacci . . . . . . . . . . . . . . . . . . . . . trace fibo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . tron decorator . . . . . . . . . . . . . . . . . . . . . . . . . . Decorate with direct call . . . . . . . . . . . . . . . . . . . Decorate with parameter . . . . . . . . . . . . . . . . . . . Decorator accepting parameter . . . . . . . . . . . . . . . Decorate function with any signature . . . . . . . . . . . Decorate function with any signature - implementation Exercise: Logger decorator . . . . . . . . . . . . . . . . . . Exercise: memoize decorator . . . . . . . . . . . . . . . . . Solution: Logger decorator . . . . . . . . . . . . . . . . . . Solution: Logger decorator (testing) . . . . . . . . . . . . . Solution memoize decorator . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
600 600 600 601 602 602 602 603 603 604 604 605 605 606 606 606 607 608
Context managers (with statement) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 610 Why use context managers? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 610 Context Manager examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
CONTENTS
cd in a function . . . . . . . . . . . . . . open in function . . . . . . . . . . . . . open in for loop . . . . . . . . . . . . . . open in function using with . . . . . . Plain context manager . . . . . . . . . . Param context manager . . . . . . . . . Context manager that returns a value Use my tempdir - return . . . . . . . . Use my tempdir - exception . . . . . . cwd context manager . . . . . . . . . . tempdir context manager . . . . . . . . Context manager with class . . . . . . Context managers with class . . . . . . Context manager: with for file . . . . . With - context managers . . . . . . . . Exercise: Context manager . . . . . . . Exercise: Tempdir on Windows . . . . Solution: Context manager . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
611 613 614 614 615 615 616 617 618 618 619 620 621 622 623 623 624 624
Advanced lists . . . . . . . . . . . . . . . . . Change list while looping: endless list Change list while looping . . . . . . . . Copy list before iteration . . . . . . . . for with flag . . . . . . . . . . . . . . . . for else . . . . . . . . . . . . . . . . . . . enumerate . . . . . . . . . . . . . . . . . do while . . . . . . . . . . . . . . . . . . list slice is copy . . . . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
626 626 626 626 627 627 628 628 629
Advanced Exception handling . . . . . . . Exceptions else . . . . . . . . . . . . . . Exceptions finally . . . . . . . . . . . . Exit and finally . . . . . . . . . . . . . . Catching exceptions . . . . . . . . . . . Home made exception . . . . . . . . . . Home made exception with attributes Home made exception hierarcy . . . . Home made exception hierarcy - 1 . . Home made exception hierarcy - 2 . . Home made exception hierarcy - 3 . . Exercise: spacefight with exceptions . Exercies: Raise My Exception . . . . . Solution: spacefight with exceptions .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
630 630 631 632 632 633 634 635 635 636 636 638 639 639
CONTENTS
Solution: Raise My Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642 Exception finally return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643 Warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644 Warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644 CSV . . . . . . . . . . . . . . . . . . . . Reading CSV the naive way . . CSV with quotes and newlines . Reading a CSV file . . . . . . . . CSV dialects . . . . . . . . . . . . CSV to dictionary . . . . . . . . . Exercise: CSV . . . . . . . . . . . Solution: CSV . . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
645 645 645 646 646 647 648 648
Excel . . . . . . . . . . . . . . . . . . . . Spreadsheets . . . . . . . . . . . . . Python Excel . . . . . . . . . . . . Create an Excel file from scratch Worksheets in Excel . . . . . . . . Add expressions to Excel . . . . . Format field . . . . . . . . . . . . . Number series and chart . . . . . Read Excel file . . . . . . . . . . . Update Excel file . . . . . . . . . . Exercise: Excel . . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
650 650 650 650 651 651 651 652 653 653 654
XML . . . . . . . . . . . . . . . . . . . . . . . XML Data . . . . . . . . . . . . . . . . . Expat - Callbacks . . . . . . . . . . . . . XML DOM - Document Object Model XML SAX - Simple API for XML . . . SAX collect . . . . . . . . . . . . . . . . XML elementtree . . . . . . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
655 655 655 656 657 658 659
SciPy - for Scientific Computing in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 Data Science tools in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 Data Analysis resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 Python and Biology . . . . Biopython . . . . . . . . Biopython background Bio python sequences . Download data . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
663 663 663 663 664
CONTENTS
Read FASTA, GenBank files Search nucleotids . . . . . . . Download nucleotids . . . . Exercise: Nucleotid . . . . . . Biology background . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
664 665 665 666 667
Chemistry . . . . . . . . . . . . . . . . . . Chemistry links . . . . . . . . . . . . Bond length . . . . . . . . . . . . . . Covalent radius . . . . . . . . . . . . Python energy landscape explorer Other chemistry links . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
668 668 668 669 669 669
numpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What is NumPy . . . . . . . . . . . . . . . . . . . . . . . Numpy - vector . . . . . . . . . . . . . . . . . . . . . . . NumPy 2D arrays . . . . . . . . . . . . . . . . . . . . . Numpy - set type . . . . . . . . . . . . . . . . . . . . . . NumPy arrays: ones and zeros . . . . . . . . . . . . . . Numpy: eye . . . . . . . . . . . . . . . . . . . . . . . . . NumPy array random . . . . . . . . . . . . . . . . . . . NumPy Random integers . . . . . . . . . . . . . . . . . NumPy array type change by division (int to float) . Numpy: Array methods: transpose . . . . . . . . . . . Numpy: reference, not copy . . . . . . . . . . . . . . . Numpy: copy array . . . . . . . . . . . . . . . . . . . . . Numpy: Elementwise Operations on Arrays . . . . . Numpy: multiply, matmul, dot for vectors . . . . . . . Numpy: multiply, matmul, dot for vector and matrix Numpy: multiply, matmul, dot for matrices . . . . . . Numpy: casting - converting from strings to integer. Numpy: indexing 1d array . . . . . . . . . . . . . . . . Numpy: slice is a reference . . . . . . . . . . . . . . . . Numpy: slice - copy . . . . . . . . . . . . . . . . . . . . Numpy: abs value on a Numpy array . . . . . . . . . . Numpy: Logical not on a Numpy array . . . . . . . . Numpy: Vectorize a function . . . . . . . . . . . . . . . Numpy: Vectorize len . . . . . . . . . . . . . . . . . . . Numpy: Vectorize lambda . . . . . . . . . . . . . . . . Numpy: Filtering array . . . . . . . . . . . . . . . . . . Numpy: Filter matrix values . . . . . . . . . . . . . . . Numpy: Filter matrix rows . . . . . . . . . . . . . . . . Numpy: Stat . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
670 670 670 670 671 671 672 673 673 674 674 675 676 676 677 677 678 679 680 680 681 681 682 683 684 684 684 685 686 687
CONTENTS
Numpy: Serialization . . . . . . . . . . . . . . . . . . . . . . . . . . . Numpy: Load from Matlab file . . . . . . . . . . . . . . . . . . . . . . Numpy: Save as Matlab file . . . . . . . . . . . . . . . . . . . . . . . . Numpy: Horizontal stack vectors (hstack) . . . . . . . . . . . . . . . Numpy: Append or vertically stack vectors and matrices (vstack) Numpy uint8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Numpy int8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
687 688 688 688 689 689 690
Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . Planets . . . . . . . . . . . . . . . . . . . . . . . . . . . Pandas Planets - Dataframes . . . . . . . . . . . . . . Pandas Stocks . . . . . . . . . . . . . . . . . . . . . . . Pandas Stocks . . . . . . . . . . . . . . . . . . . . . . . Merge Dataframes . . . . . . . . . . . . . . . . . . . . Analyze Alerts . . . . . . . . . . . . . . . . . . . . . . Analyze IFMetrics . . . . . . . . . . . . . . . . . . . . Create Excel file for experiment with random data Calculate Genome metrics . . . . . . . . . . . . . . . Calculate Genome metrics - add columns . . . . . . Calculate Genome metrics - vectorized . . . . . . . Calculate Genome metrics - vectorized numpy . . . Genes using Jupyter . . . . . . . . . . . . . . . . . . . Combine columns . . . . . . . . . . . . . . . . . . . . Pandas more . . . . . . . . . . . . . . . . . . . . . . . . Pandas Series . . . . . . . . . . . . . . . . . . . . . . . Pandas Series with names . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
691 691 691 691 692 693 693 695 695 695 696 697 698 698 699 699 700 701 702
Matplotlib . . . . . . . . . . . . . . . . . . About Matplotlib . . . . . . . . . . . Matplotlib Line . . . . . . . . . . . . Matplotlib Line with dates . . . . . Matplotlib Simple Pie . . . . . . . . Matplotlib Simple Pie with params Matplotlib Pie . . . . . . . . . . . . . Matplotlib Pie 2 . . . . . . . . . . . . Plot, scatter, histogram . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
704 704 704 705 706 707 708 709 710
Seaborn . . . . . . . . . . . . . . . Searborn use examples . . . Seaborn tip . . . . . . . . . . . Seaborn Anscombes Quartet
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
711 711 711 712
. . . .
. . . .
. . . .
. . . .
Jupyter notebooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714
CONTENTS
Jupyter on Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jupyter on Linux and OSX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jupyter add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Planets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jupyter notebook Planets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - selected columns . . . . . . . . . . . . . . . . . . . . . . Jupyter processing chunks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - selected rows . . . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - biggest countries (in terms of number of responses) Jupyter StackOverflow - historgram . . . . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - filter by country . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - OpenSourcer . . . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - cross tabulation . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - salaries . . . . . . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - replace values . . . . . . . . . . . . . . . . . . . . . . . Jupyter StackOverflow - selected rows . . . . . . . . . . . . . . . . . . . . . . . . Jupyter notebook Intellisense (TAB completition) . . . . . . . . . . . . . . . . . Jupyter examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IPy Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
714 714 714 715 715 716 717 717 717 718 719 719 719 719 720 720 720 721 721 721
Testing . . . . . . . . . . . . . . . . . . . . Traditional Organizations . . . . . . Quality Assurance . . . . . . . . . . Web age Organizations . . . . . . . TDD vs Testing as an Afterthought Why test? . . . . . . . . . . . . . . . Testing Modes . . . . . . . . . . . . . Testing Applications . . . . . . . . . Testing What to test? . . . . . . . . Testing in Python . . . . . . . . . . . Testing Environment . . . . . . . . . Testing Setup - Fixture . . . . . . . . Testing Resources . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
722 722 722 722 722 723 723 723 723 724 724 724 724
Testing with unittest . Use a module . . . Test a module . . . The tested module Testing - skeleton . Testing . . . . . . . Test examples . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
725 725 725 726 726 727 728
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
Testing with PyTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 729
CONTENTS
Pytest features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Testing with Pytest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Testing functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Testing class and methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest - execute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest - execute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest simple module to be tested . . . . . . . . . . . . . . . . . . . . . . . . Pytest simple tests - success . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest simple tests - success output . . . . . . . . . . . . . . . . . . . . . . . Pytest simple tests - failure . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest simple tests - failure output . . . . . . . . . . . . . . . . . . . . . . . Exercise: test math functions . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: test this app . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: test the csv module . . . . . . . . . . . . . . . . . . . . . . . . . . . Solution: Pytest test math functions . . . . . . . . . . . . . . . . . . . . . . . Solution: Pytest test this app . . . . . . . . . . . . . . . . . . . . . . . . . . . Solution: test the csv module . . . . . . . . . . . . . . . . . . . . . . . . . . . PyTest bank deposit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PyTest expected exceptions (bank deposit) . . . . . . . . . . . . . . . . . . . PyTest expected exceptions (bank deposit) - no exception happens . . . . PyTest expected exceptions (bank deposit) - different exception is raised PyTest expected exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . PyTest expected exceptions output . . . . . . . . . . . . . . . . . . . . . . . PyTest expected exceptions (text changed) . . . . . . . . . . . . . . . . . . . PyTest expected exceptions (text changed) output . . . . . . . . . . . . . . PyTest expected exceptions (other exception) . . . . . . . . . . . . . . . . . PyTest expected exceptions (other exception) output . . . . . . . . . . . . PyTest expected exceptions (no exception) . . . . . . . . . . . . . . . . . . . PyTest expected exceptions (no exception) output . . . . . . . . . . . . . . PyTest: Multiple Failures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PyTest: Multiple Failures output . . . . . . . . . . . . . . . . . . . . . . . . . PyTest Selective running of test functions . . . . . . . . . . . . . . . . . . . PyTest: stop on first failure . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest: expect a test to fail (xfail or TODO tests) . . . . . . . . . . . . . . . Pytest: expect a test to fail (xfail or TODO tests) . . . . . . . . . . . . . . . PyTest: show xfailed tests with -rx . . . . . . . . . . . . . . . . . . . . . . . Pytest: skipping tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest: show skipped tests woth -rs . . . . . . . . . . . . . . . . . . . . . . . Pytest: show extra test summmary info with -r . . . . . . . . . . . . . . . . Pytest: skipping tests output in verbose mode . . . . . . . . . . . . . . . . . Pytest verbose mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pytest quiet mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
729 729 729 730 730 731 731 731 731 732 732 732 733 733 734 734 735 735 736 736 737 738 738 738 739 739 739 740 740 741 741 742 742 742 742 743 743 744 745 745 745 746 746
CONTENTS
PyTest print STDOUT and STDERR using -s . . . . PyTest failure reports . . . . . . . . . . . . . . . . . . PyTest compare numbers . . . . . . . . . . . . . . . . PyTest compare numbers relatively . . . . . . . . . . PyTest compare strings . . . . . . . . . . . . . . . . . PyTest compare long strings . . . . . . . . . . . . . . PyTest is one string in another strings . . . . . . . . PyTest test any expression . . . . . . . . . . . . . . . PyTest element in list . . . . . . . . . . . . . . . . . . PyTest compare lists . . . . . . . . . . . . . . . . . . . PyTest compare short lists . . . . . . . . . . . . . . . PyTest compare short lists - verbose output . . . . . PyTest compare dictionaries . . . . . . . . . . . . . . PyTest compare dictionaries output . . . . . . . . . . PyTest Fixtures . . . . . . . . . . . . . . . . . . . . . . PyTest Fixture setup and teardown . . . . . . . . . . PyTest Fixture setup and teardown output . . . . . . PyTest: Class setup and teardown . . . . . . . . . . . PyTest: Class setup and teardown output . . . . . . Pytest Dependency injection . . . . . . . . . . . . . . Pytest fixture - tmpdir . . . . . . . . . . . . . . . . . . Pytest capture STDOUT and STDERR with capsys Pytest Fixture - home made fixtures . . . . . . . . . More fixtures . . . . . . . . . . . . . . . . . . . . . . . Pytest: Mocking - why? . . . . . . . . . . . . . . . . . Pytest: Mocking - what? . . . . . . . . . . . . . . . . . Pytest: One dimensional spacefight . . . . . . . . . . Pytest: Mocking input and output . . . . . . . . . . . Pytest: Mocking random . . . . . . . . . . . . . . . . Pytest: Flask echo . . . . . . . . . . . . . . . . . . . . . Pytest: testing Flask echo . . . . . . . . . . . . . . . . PyTest: Run tests in parallel with xdist . . . . . . . . PyTest: Order of tests . . . . . . . . . . . . . . . . . . PyTest: Randomize Order of tests . . . . . . . . . . . PyTest: Force default order . . . . . . . . . . . . . . . PyTest: no random order . . . . . . . . . . . . . . . . Anagram on the command line . . . . . . . . . . . . PyTest testing CLI . . . . . . . . . . . . . . . . . . . . PyTest test discovery . . . . . . . . . . . . . . . . . . . PyTest test discovery - ignore some tests . . . . . . . PyTest select tests by name . . . . . . . . . . . . . . . PyTest select tests by marker . . . . . . . . . . . . . . PyTest: Test Coverage . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
747 747 747 747 748 748 749 750 750 750 751 751 752 752 753 753 754 755 756 756 757 757 758 759 761 761 761 763 763 764 765 766 766 766 766 767 767 767 768 769 770 771 772
CONTENTS
Exercise: module . . . . . . . . . . . . . Exercise: Open Source . . . . . . . . . . Pytest resources . . . . . . . . . . . . . . Pytest and tempdir . . . . . . . . . . . . PyTest compare short lists - output . . PyTest with parameter . . . . . . . . . . PyTest with parameters . . . . . . . . . Pytest reporting in JUnit XML format No test selected . . . . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
772 773 773 773 774 775 776 776 777
Advancted functions . . . . . . . . . . . . . . . . . . . . . . . . . Variable scopes . . . . . . . . . . . . . . . . . . . . . . . . . . Name resolution order (LEGB) . . . . . . . . . . . . . . . . . Scoping: global seen from fuction . . . . . . . . . . . . . . . Assignment creates local scope . . . . . . . . . . . . . . . . Local scope gone wrong . . . . . . . . . . . . . . . . . . . . . Changing global variable from a function . . . . . . . . . . Global variables mutable in functions . . . . . . . . . . . . Scoping issues . . . . . . . . . . . . . . . . . . . . . . . . . . . sub in sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Scoping sub in sub (enclosing scope) . . . . . . . . . . . . . Function objects . . . . . . . . . . . . . . . . . . . . . . . . . Functions are created at run time . . . . . . . . . . . . . . . Mutable default . . . . . . . . . . . . . . . . . . . . . . . . . . Use None as default parameter . . . . . . . . . . . . . . . . Inner function created every time the outer function runs Static variable . . . . . . . . . . . . . . . . . . . . . . . . . . . Static variable in generated function . . . . . . . . . . . . . Inspect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
778 778 778 778 778 779 780 780 780 781 781 782 782 783 783 784 785 785 786
Variable number of function arguments . . . . . . . . . . . . . Python function arguments - a reminder . . . . . . . . . . . Functions with unknown number of argumerns . . . . . . . Variable length argument list with * and ** . . . . . . . . . . Passing arguments as they were received (but incorrectly) . Unpacking args before passing them on . . . . . . . . . . . . Exercise: implement the my_sum function . . . . . . . . . . Solution: implement the my_sum function . . . . . . . . . . Exercise: implement the reduce function . . . . . . . . . . . . Soluton: implement the reduce function . . . . . . . . . . . . Exercise: sort pairs . . . . . . . . . . . . . . . . . . . . . . . . . Solution: sort pairs . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
788 788 788 789 789 790 790 791 791 791 792 792
Python Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 794
CONTENTS
Why Create package . . . . . . . . . . . . . . . . . . . . Create package . . . . . . . . . . . . . . . . . . . . . . . Internal usage . . . . . . . . . . . . . . . . . . . . . . . . use module in package - relative path . . . . . . . . . use package (does not work) . . . . . . . . . . . . . . . package importing (and exporting) module . . . . . . use package (module) with import . . . . . . . . . . . use package with import . . . . . . . . . . . . . . . . . Creating an installable Python package . . . . . . . . Create tar.gz file . . . . . . . . . . . . . . . . . . . . . . Install Package . . . . . . . . . . . . . . . . . . . . . . . Dependencies . . . . . . . . . . . . . . . . . . . . . . . . Add README file . . . . . . . . . . . . . . . . . . . . . Add README file (setup.py) . . . . . . . . . . . . . . . Include executables . . . . . . . . . . . . . . . . . . . . . Add tests . . . . . . . . . . . . . . . . . . . . . . . . . . . Add tests calc . . . . . . . . . . . . . . . . . . . . . . . . Add tests all . . . . . . . . . . . . . . . . . . . . . . . . . setup.py . . . . . . . . . . . . . . . . . . . . . . . . . . . Run tests and create package . . . . . . . . . . . . . . . Packaging applications (creating executable binaries) Using PyInstaller . . . . . . . . . . . . . . . . . . . . . . Other PyInstaller examples . . . . . . . . . . . . . . . . Other . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Py2app for Mac . . . . . . . . . . . . . . . . . . . . . . . Exercise: package . . . . . . . . . . . . . . . . . . . . . . Exercise: create executable . . . . . . . . . . . . . . . . Ctypes . . . . . . . ctypes - hello concat . . . . . links . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
794 794 794 795 795 796 796 796 797 797 798 799 799 800 800 801 802 802 803 803 803 804 804 804 804 805 805
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
806 806 807 808
Advanced OOP . . . . . . . . . . . . . . Class count instances . . . . . . . . Class Attributes . . . . . . . . . . . . Class Attributes in Instances . . . . Attributes with method access . . . Instance Attribute . . . . . . . . . . Methods are class attributes . . . . Monkey patching . . . . . . . . . . . Classes: instance method . . . . . . Class methods and class attributes
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
809 809 809 810 811 811 812 813 814 815
CONTENTS
Classes: constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . Class methods - alternative constructor . . . . . . . . . . . . . . . Abstract Base Class . . . . . . . . . . . . . . . . . . . . . . . . . . . Abstract Base Class with abc . . . . . . . . . . . . . . . . . . . . . . ABC working example . . . . . . . . . . . . . . . . . . . . . . . . . ABC - cannot instantiate the base-class . . . . . . . . . . . . . . . ABC - must implement methods . . . . . . . . . . . . . . . . . . . Use Python @propery to fix bad interface (the bad interface) . . Use Python @propery to fix bad interface (first attempt) . . . . . Use Python @propery to fix bad API . . . . . . . . . . . . . . . . . Use Python @propery decorator to fix bad API . . . . . . . . . . Use Python @propery for value validation . . . . . . . . . . . . . class and static methods . . . . . . . . . . . . . . . . . . . . . . . . . Destructor: del . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Destructor delayed . . . . . . . . . . . . . . . . . . . . . . . . . . . . Destructor delayed for both . . . . . . . . . . . . . . . . . . . . . . Opearator overloading . . . . . . . . . . . . . . . . . . . . . . . . . . Operator overloading methods . . . . . . . . . . . . . . . . . . . . . Exercise: rectangular . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: SNMP numbers . . . . . . . . . . . . . . . . . . . . . . . . Exercise: Implement a Gene inheritance model combining DNA Exercise: imaginary numbers - complex numbers . . . . . . . . . Solution: Rectangular . . . . . . . . . . . . . . . . . . . . . . . . . . Solution: Implement a Gene inheritance model combining DNA Instance counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2to3 . . . . . . . . . . . . . . . . . . . . . . . . Convertig from Python 2 to Python 3 division . . . . . . . . . . . . . . . . . . . print in Python 2 . . . . . . . . . . . . . print in Python 3 . . . . . . . . . . . . . input and raw_input . . . . . . . . . . . Code that works on both 2 and 3 . . . Compare different types . . . . . . . . . Octal numbers . . . . . . . . . . . . . . 2to3 Resources . . . . . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
816 817 818 819 819 820 820 821 821 822 823 824 825 827 828 828 829 830 830 831 831 831 832 835 836
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
837 837 837 837 837 838 838 838 839 839
Design Patterns . . . . . . . . . . . . . . . . . . . . What are Design Patterns? . . . . . . . . . . . Don’t replace built-in objects . . . . . . . . . Facade - simple interface to complex system Monkey Patching . . . . . . . . . . . . . . . . . Creation DPs “Just One” . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
840 840 840 840 841 842
CONTENTS
Singleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 842 Monostate (Borg) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 843 Dispatch table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 843 Parallel . . . . . . . . . . . . . . . Types of Problems . . . . . . Types of solutions . . . . . . How many parallels to use? Dividing jobs . . . . . . . . . Performance Monitoring . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
844 844 844 844 844 845
Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Threading docs . . . . . . . . . . . . . . . . . . Threaded counters . . . . . . . . . . . . . . . . . . . . . Simple threaded counters . . . . . . . . . . . . . . . . . Simple threaded counters (parameterized) . . . . . . . Pass parameters to threads - Counter with attributes Create a central counter . . . . . . . . . . . . . . . . . . Lock - acquire - release . . . . . . . . . . . . . . . . . . Counter - plain . . . . . . . . . . . . . . . . . . . . . . . GIL - Global Interpreter Lock . . . . . . . . . . . . . . Thread load . . . . . . . . . . . . . . . . . . . . . . . . . Exercise: thread files . . . . . . . . . . . . . . . . . . . . Exercise: thread URL requests. . . . . . . . . . . . . . . Exercise: thread queue . . . . . . . . . . . . . . . . . . . Solution: thread queue . . . . . . . . . . . . . . . . . . . Solution: thread URL requests. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
846 846 846 847 849 850 852 852 853 854 855 856 856 859 860 861
Forking . . . . . . . . . . . . . . Fork . . . . . . . . . . . . . . Forking . . . . . . . . . . . . Fork skeleton . . . . . . . . Fork with load . . . . . . . . Fork load results . . . . . . Marshalling / Serialization Fork with random . . . . . Exercise: fork return data . Solution: fork return data .
. . . . . . . . . .
. . . . . .
. . . . . . . . . .
. . . . . .
. . . . . . . . . .
. . . . . .
. . . . . . . . . .
. . . . . .
. . . . . . . . . .
. . . . . .
. . . . . . . . . .
. . . . . .
. . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
863 863 863 864 865 866 867 868 868 869
Asyncronus programming with AsyncIO Sync chores . . . . . . . . . . . . . . . . . Async chores . . . . . . . . . . . . . . . . Explanation . . . . . . . . . . . . . . . . . Coroutines . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
871 871 873 875 876
CONTENTS
More about asyncio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 876 Async files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 876 Asynchronus programming with Twisted About Twisted . . . . . . . . . . . . . . . Echo . . . . . . . . . . . . . . . . . . . . . . Echo with log . . . . . . . . . . . . . . . . Simple web client . . . . . . . . . . . . . . Web client . . . . . . . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
877 877 877 878 879 880
Multiprocess . . . . . . . . . . . . . . . . . . . . Multiprocess CPU count . . . . . . . . . . Multiprocess Process . . . . . . . . . . . . . Multiprocess N files: Pool . . . . . . . . . . Multiprocess load . . . . . . . . . . . . . . . Multiprocess: Pool . . . . . . . . . . . . . . Multiprocess load async . . . . . . . . . . . Multiprocess and logging . . . . . . . . . . Exercise: Process N files in parallel . . . . Exercise: Process N Excel files in parallel Exercise: Fetch URLs in parallel . . . . . . Exercise: Fetch URLs from one site. . . . . Solution: Fetch URLs in parallel . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
883 883 883 883 884 885 886 887 888 888 889 891 892
Multitasking . . . . . . . . . . . . . . . . . . . . . . . What is Multitasking? . . . . . . . . . . . . . . . Multitasking example . . . . . . . . . . . . . . . Multitasking example with wait . . . . . . . . . Multitaksing - second loop waits for first one . Multitasking counter . . . . . . . . . . . . . . . . Multitasking counter with thread locking . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
895 895 895 896 897 898 899
Improving Performance - Optimizing code Problems . . . . . . . . . . . . . . . . . . . . Optimization strategy . . . . . . . . . . . . Locate the source of the problem . . . . . Optimizing tactics . . . . . . . . . . . . . . DSU: Decorate Sort Undecorate . . . . . . Profile code . . . . . . . . . . . . . . . . . . Slow example . . . . . . . . . . . . . . . . . profile slow code . . . . . . . . . . . . . . . cProfile slow code . . . . . . . . . . . . . . Benchmarking . . . . . . . . . . . . . . . . . Benchmarking subs . . . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
900 900 900 900 900 901 901 901 903 903 904 905
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
CONTENTS
Levenshtein distance . . . . . . . . . . . . . . . . . . . Generate words . . . . . . . . . . . . . . . . . . . . . . Levenshtein - pylev . . . . . . . . . . . . . . . . . . . Levenshtein - editdistance . . . . . . . . . . . . . . . Editdistance benchmark . . . . . . . . . . . . . . . . . A Tool to Generate text files . . . . . . . . . . . . . . Count characters . . . . . . . . . . . . . . . . . . . . . Memory leak . . . . . . . . . . . . . . . . . . . . . . . Garbage collection . . . . . . . . . . . . . . . . . . . . Weak reference . . . . . . . . . . . . . . . . . . . . . . Exercise: benchmark list-comprehension, map, for . Exercise: Benchmark Levenshtein . . . . . . . . . . . Exercise: sort files . . . . . . . . . . . . . . . . . . . . Exercise: compare split words: . . . . . . . . . . . . . Exercise: count words . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
905 906 906 907 907 907 909 910 911 912 913 913 913 913 914
GUI with Python/Tk . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sample Tk app . . . . . . . . . . . . . . . . . . . . . . . . . . . . . GUI Toolkits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Documentation . . . . . . . . . . . . . . . . . . . . . . Python Tk Button . . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Button with action . . . . . . . . . . . . . . . . . . . . Python Tk Label . . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Label - font size and color . . . . . . . . . . . . . . . . Python Tk Keybinding . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Entry (one-line text entry) . . . . . . . . . . . . . . . Python Tk Entry for passwords and other secrets (hidden text) Python Tk Checkbox . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Radiobutton . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Listbox . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Listbox Multiple . . . . . . . . . . . . . . . . . . . . . Python Tk Menubar . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Filedialog . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk messagebox . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Combobox . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk OptionMenu . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Scale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Progressbar . . . . . . . . . . . . . . . . . . . . . . . . Python Tk Frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . Not so Simple Tk app with class . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
916 916 920 920 921 921 922 922 923 923 924 925 925 926 927 927 928 930 930 930 932 933 934 935 936 936 938
CONTENTS
Tk: Hello World . . . . . . . . . . . . . . . . . . Tk: Quit button . . . . . . . . . . . . . . . . . . Tk: File selector . . . . . . . . . . . . . . . . . . Tk: Checkbox . . . . . . . . . . . . . . . . . . . Tk: Runner . . . . . . . . . . . . . . . . . . . . . Tk: Runner with threads . . . . . . . . . . . . Getting started with Tk . . . . . . . . . . . . . Exercise: Tk - Calculator one line . . . . . . . Exercise: Tk Shopping list . . . . . . . . . . . . Exercise: Tk TODO list . . . . . . . . . . . . . Exercise: Tk Notepad . . . . . . . . . . . . . . Exercise: Tk Copy files . . . . . . . . . . . . . Exercise: Tk Implement Master Mind board . Exercise: Tk . . . . . . . . . . . . . . . . . . . . Solution: Tk - Calculator one line . . . . . . . Solution: Tk Implement Master Mind board . Solution: Tk . . . . . . . . . . . . . . . . . . . . Solution: Tk Notepad . . . . . . . . . . . . . . Simple file dialog . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
938 939 940 941 942 944 948 949 949 950 950 950 950 950 951 953 953 954 956
Python Pitfalls . . . . . . . . . . . . . . . . Reuse of existing module name . . . Use the same name more than once . Compare string and number . . . . . Compare different types . . . . . . . . Sort mixed data . . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
957 957 957 958 959 959
Linters . . . . . . . . . . . . . . . . . . . Static Code Analyzis - Linters . . PEP8 . . . . . . . . . . . . . . . . . F811 - redefinition of unused . . . Warn when Redefining functions
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
961 961 961 961 961
Python .NET . . . . . . . . . . . . . . IronPython . . . . . . . . . . . . . Use .NET libraries from Python Python and .NET console . . . . Python and .NET examples . . . Exercise Python and .NET . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
963 963 963 964 964 966
. . . . . .
Python and Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 967 Jython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 967 Calling Java from Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 967
CONTENTS
Jython - Python running on the JVM Jython Installation . . . . . . . . . . Jython Installation . . . . . . . . . . Jython load Java class . . . . . . . . Jython load Java class in code . . . Jython test Java class . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
968 968 968 968 968 969
PIL - Pillow . . . . . . . . . . . . . . . . . . . . . . . . Install Pillow . . . . . . . . . . . . . . . . . . . . Create First Image . . . . . . . . . . . . . . . . . Write Text on Image . . . . . . . . . . . . . . . . Select font for Text on Image . . . . . . . . . . . Font directories . . . . . . . . . . . . . . . . . . . Get size of an Image . . . . . . . . . . . . . . . . Get size of text . . . . . . . . . . . . . . . . . . . Resize an existing Image . . . . . . . . . . . . . Crop an existing Image . . . . . . . . . . . . . . Combine two images . . . . . . . . . . . . . . . Rotated text . . . . . . . . . . . . . . . . . . . . . Rotated text in top-right corner . . . . . . . . . Embed image (put one image on another one) Draw a triangle . . . . . . . . . . . . . . . . . . . Draw a triangle and write text in it . . . . . . . Draw a triangle and write rotated text in it . . Draw a rectangular . . . . . . . . . . . . . . . . . Draw a rectangle . . . . . . . . . . . . . . . . . . Draw circle . . . . . . . . . . . . . . . . . . . . . Draw heart . . . . . . . . . . . . . . . . . . . . . . Rectangle with rounded corners . . . . . . . . . TODO . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
970 970 970 970 971 971 972 972 972 973 973 973 974 975 975 975 976 977 977 977 977 978 979
FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How not to name example scirpts? . . . . . . . . . . . . . . Platform independent code . . . . . . . . . . . . . . . . . . . How to profile a python code to find causes of slowness? pdb = Python Debugger . . . . . . . . . . . . . . . . . . . . . Avoid Redefining functions . . . . . . . . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
980 980 980 980 981 981
Appendix . . . . . . . . . . . . . . . . print_function . . . . . . . . . . . Dividers (no break or continue) Lambdas . . . . . . . . . . . . . . Abstract Class . . . . . . . . . . . Remove file . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
982 982 982 982 983 984
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
CONTENTS
Modules: more . . . . . . . . . . . . . import hooks . . . . . . . . . . . . . . Python resources . . . . . . . . . . . . Progress bar . . . . . . . . . . . . . . . from future . . . . . . . . . . . . . . . Variable scope . . . . . . . . . . . . . . scope . . . . . . . . . . . . . . . . . . . type . . . . . . . . . . . . . . . . . . . . Look deeper in a list . . . . . . . . . . Exercise: iterators - count . . . . . . . Simple function (before generators) .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
984 985 985 985 985 986 987 989 990 990 990
Other slides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Other slides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Atom for Python . . . . . . . . . . . . . . . . . . . . . . . . . . IDLE - Integrated DeveLopment Environment . . . . . . . . sh-bang - executable on Linux/Apple . . . . . . . . . . . . . . Strings as Comments . . . . . . . . . . . . . . . . . . . . . . . pydoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How can I check if a string can be converted to a number? Spyder Intro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interactive Debugging . . . . . . . . . . . . . . . . . . . . . . . Parameter passing . . . . . . . . . . . . . . . . . . . . . . . . . Command line arguments and main . . . . . . . . . . . . . . Infinite loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . While with many conditions . . . . . . . . . . . . . . . . . . . while loop with many conditions . . . . . . . . . . . . . . . . Format with conversion (stringifiation with str or repr) . . Name of the current function in Python . . . . . . . . . . . . Name of the caller function in Python . . . . . . . . . . . . . Stack trace in Python using inspect . . . . . . . . . . . . . . . Module Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . . PyTest - assertion . . . . . . . . . . . . . . . . . . . . . . . . . . PyTest - failure . . . . . . . . . . . . . . . . . . . . . . . . . . . PyTest - list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SAX with coroutine . . . . . . . . . . . . . . . . . . . . . . . . Getting the class name of an object . . . . . . . . . . . . . . . Inheritance - super . . . . . . . . . . . . . . . . . . . . . . . . . Inheritance - super - other class . . . . . . . . . . . . . . . . . iterator - pairwise . . . . . . . . . . . . . . . . . . . . . . . . . iterator - grouped . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. 992 . 992 . 992 . 993 . 993 . 993 . 994 . 994 . 995 . 995 . 996 . 996 . 996 . 996 . 997 . 997 . 998 . 998 . 999 .1000 .1000 .1002 .1002 .1003 .1003 .1004 .1006 .1007 .1008 .1009 .1009
CONTENTS
itertools - groupby . . . . . . . . . . . . . . . Circular references . . . . . . . . . . . . . . . Context managers: with (file) experiments itertools - izip . . . . . . . . . . . . . . . . . . mixing iterators . . . . . . . . . . . . . . . . . mixing iterators . . . . . . . . . . . . . . . . . itertools - pairwise . . . . . . . . . . . . . . . itertools - grouped . . . . . . . . . . . . . . . range vs xrange in Python . . . . . . . . . . profile (with hotshot) slow code . . . . . . . Abstract Base Class without abc . . . . . . . Abstract Base Class with abc Python 2 ? . . Abstract Base Class with metaclass . . . . . Create class with metaclass . . . . . . . . . . Python Descriptors . . . . . . . . . . . . . . . alter iterator . . . . . . . . . . . . . . . . . . . Create a counter queue . . . . . . . . . . . . A Queue of tasks . . . . . . . . . . . . . . . . Filtered Fibonacci with ifilter . . . . . . . . . Python from .NET . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
.1010 .1010 .1011 .1011 .1012 .1012 .1013 .1013 .1014 .1014 .1015 .1016 .1017 .1019 .1022 .1022 .1022 .1023 .1024 .1024
Fixtures and Mocking in Python How do you test Moon-landing? • without actually flying to the moon?
How do you test a system … • • • • • •
that sends a verification email? that relies on random values? in parallel without interference? together with a 3rd party? when a 3rd party it uses fails? with a timeout
Plan • • • • •
Introducton Presentation about Fixtures and Mocking Hands-on exercises Retrospective Job searching help
About me • • • • • •
Gabor Szabo¹ Help tech teams move faster with more stability and more predictability. Automation DevOps Code Maven Workshops² Code Maven Workshops on Meetup³
¹https://www.linkedin.com/in/szabgab/ ²https://workshops.code-maven.com/ ³https://www.meetup.com/Code-Mavens/
Fixtures and Mocking in Python
Goal You will come out from the workshop knowing • • • •
What are Fixtures? What is Mocking and Monkey Patching? When to use them? What are the dangers?
• Experiment with mocking in various situations.
Fixtures * Fixtures - the environment in which a test runs (the outside world) • Directory layout - files • Database with or without data etc.
Fixtuers in Pytest • A more generic term • Helper tools to run and analyze your test code
Traditional xUnit fixtures 1 2
def setup_module(): print("setup_module")
3 4 5
def teardown_module(): print("teardown_module")
6 7 8 9
def setup_function(): print(" setup_function")
10 11 12 13
def teardown_function(): print(" teardown_function")
2
Fixtures and Mocking in Python 14 15 16 17 18
def test_one(): print(" test_one") assert True print(" test_one after")
19 20 21 22 23
def test_two(): print(" test_two") assert False print(" test_two after")
24 25 26 27 28
1
def test_three(): print(" test_three") assert True print(" test_three after")
$ pytest test_fixture.py -s
2 3
setup_module
4 5 6 7 8
setup_function test_one test_one after teardown_function
9 10 11 12
setup_function test_two teardown_function
13 14 15 16 17
setup_function test_three test_three after teardown_function
18 19
teardown_module
Dependency Injection • Use introspection to find out what a method needs • Pass in the right arguments
3
Fixtures and Mocking in Python 1 2
4
def do_something(name, age): pass
Temporary directory - tmpdir • tmpdir 1
import json
2 3 4 5
def read(filename): with open(filename) as fh: return json.load(fh)
6 7 8 9 1 2
def save(filename, data): with open(filename, 'w') as fh: return json.dump(data, fh) import app import os
3 4 5 6
def test_json(tmpdir): tdir = str(tmpdir) print(tdir)
7 8 9 10 11
data = { 'name' : 'Foo Bar', 'email' : '[email protected]', }
12 13 14 15 16
filename = os.path.join(tdir, 'temp.json') app.save(filename, data) again = app.read(filename) assert data == again
• Directory location OSX: /private/var/folders/ry/z60xxmw0000gn/T/pytest-of-gabor/pytest-14/test_read0 • Linux: /tmp/pytest-of-gabor/pytest-9/test_json0 • Directory cleanup
Capture STDOUT and STDERR - capsys • capsys
Fixtures and Mocking in Python 1
import sys
2
6
def greet(to_out, to_err=None): print(to_out) if to_err: print(to_err, file=sys.stderr)
1
import app
3 4 5
2 3 4 5 6 7
def test_myoutput(capsys): app.greet("hello", "world") out, err = capsys.readouterr() assert out == "hello\n" assert err == "world\n"
8 9 10 11 12
app.greet("next") out, err = capsys.readouterr() assert out == "next\n" assert err == ""
Home-made fixture 1
import pytest
2 3 4 5 6 7 8
@pytest.fixture() def config(): return { 'name' : 'Foo Bar', 'email' : '[email protected]', }
9 10 11 12
def test_some_data(config): assert True print(config)
Home-made fixture - conftest
5
6
Fixtures and Mocking in Python
3
def test_some_data(config): assert True print(config)
1
import pytest
1 2
2 3 4 5 6 7 8
@pytest.fixture() def config(): return { 'name' : 'Foo Bar', 'email' : '[email protected]', }
Home-made fixture with tempdir 1
import yaml
2 3 4 5
def test_some_data(config): assert True print(config)
6 7 8 9
1 2 3
with open(config) as fh: conf = yaml.load(fh, Loader=yaml.FullLoader) print(conf)
import pytest import os import yaml
4 5 6 7 8 9
@pytest.fixture() def config(tmpdir): print(tmpdir.__class__) tdir = str(tmpdir) print(tdir)
# LocalPath
10 11 12 13 14 15
config_data = { 'name' : 'Foo Bar', 'email' : '[email protected]', } config_file = os.path.join(tdir, 'test_db.yaml')
Fixtures and Mocking in Python 16 17
with open(config_file, 'w') as yaml_file: yaml.dump(config_data, yaml_file, default_flow_style=False)
18 19
1 2
return config_file
$ pytest -qs {'name': 'Foo Bar', 'email': '[email protected]'}
Home-made fixture with yield 1
import pytest
2 3 4 5
@pytest.fixture() def configuration(): print("Before")
6 7
yield { 'name' : 'Foo Bar' }
8 9
1 2 3 4
1 2 3 4 5
print("After")
def test_app(configuration): print("In test") print(configuration) assert True
$ pytest -sq Before In test {'name': 'Foo Bar'} .After
6 7
1 passed in 0.02 seconds
Fixture Autouse
7
Fixtures and Mocking in Python 1
import pytest
2 3 4 5
1 2 3
1 2 3 4
@pytest.fixture(autouse = True) def configuration(): print("Before")
def test_app(): print("In test") assert True
$ pytest -sq Before In test .
5 6
1 passed in 0.02 seconds
Fixture Autouse with yield 1
import pytest
2 3 4 5
@pytest.fixture(autouse = True) def configuration(): print("Before")
6 7
yield
8 9
1 2 3
print("After")
def test_app(): print("In test") assert True
8
Fixtures and Mocking in Python 1 2 3 4
$ pytest -sq Before In test .After
5 6
1 passed in 0.02 seconds
Fixture for MongoDB 1 2
import pytest import os, time
3 4
from app.common import get_mongo
5 6 7 8 9
@pytest.fixture(autouse = True) def configuration(): dbname = 'test_app_' + str(int(time.time())) os.environ['APP_DB_NAME'] = dbname
10
yield
11 12
get_mongo().drop_database(dbname)
13
Test Doubles • • • • •
Mocks Spies Stubs Fakes Dummies
• Gerard Meszaros - xUnit Test Patterns⁴ • Test Double explained by Martin Fowler⁵
Test Doubles explained Dummy objects are passed around but never actually used. Fakes - Working implementation, but much simple ⁴https://martinfowler.com/books/meszaros.html ⁵https://martinfowler.com/bliki/TestDouble.html
9
Fixtures and Mocking in Python
10
• An in-memory list of username/password pairs that provide the authentication) • A database interface where data stored in memory only, maybe in a dictionary. Mocks - Mocks are objects that register calls they receive, but do not execute the real system behind. Stubs - Stub is an object that holds predefined data and uses it to answer calls during tests. • A list of “random values” • Responses given to prompt Spies usually record some information based on how they were called and then call the real method. (or not)
Verify behavior or state? What is Mocking and Monkey Patching? • Replace some internal part of a module or class for the sake of testing. • Mocking • Monkey Patching
Situations • • • • • • •
TDD Write application agains API that is not ready yet or not controlled by you. Replace a complex object with a simpler one. Isolate parts of the system to test them on their own. Speed up tests (e.g. eliminate remote calls, eliminate database calls). Simulate cases that are hard to replicate. (What if the other system fails?) Unit tests.
11
Fixtures and Mocking in Python
Unit testing vs. Integration testing
View this Video at resources/img/dryer.mp4⁶. dryer
Experiment with mocking in various situations • • • • •
Mocking external calls. Mocking method calls. Mocking a whole class. Mocking time. Mocking IO
Examples are simple • Don’t worry, real life code is much more complex!
Hard coded path In many application we can find hard-coded pathes. In order to test them we will need to create that exact path which is not always easy. This also means we cannot run two tests at the same time with different content in those files. (The actual “application” is just adding numbers together.)
Fixtures and Mocking in Python 1
12
import json
2 3
data_file = "/corporate/fixed/path/data.json"
4 5 6 7 8 9 10
1
def get_sum(): with open(data_file) as fh: data = json.load(fh) # ... result = data['x'] + data['y'] return result
import app
2 3 4 5
def test_sum(): res = app.get_sum() assert True
pytest test_data_1.py 1 2 3 4
def get_sum(): > with open(data_file) as fh: E FileNotFoundError: [Errno 2] No such file or directory: '/corporate/fixed/pa\ th/data.json'
Manually Patching attribute We can replace the attribute during the test run and create a json file locally to be used. At least two problems with this: • Readers might glance over the assignment and might be baffled • The change is permanent in the whole test script so one test impacts the other.
13
Fixtures and Mocking in Python 1
import app
2 3 4
def test_sum(): app.data_file = 'test_1.json'
# manually overwrite
5
res = app.get_sum() assert True assert res == 42
6 7 8 9 10 11
1
def test_again(): print(app.data_file)
{ "x": 19, "y": 23
2 3 4
# it is still test_1.json
}
Monkey Patching attribute We can use the monkeypatch fixture to do the same. • It stands out more as it is a fxture and you can search for the name • It only applies to the current test function. So they are now independent again.
1
import app
2 3 4
def test_sum(monkeypatch): monkeypatch.setattr(app, 'data_file', 'test_1.json')
5 6 7 8
res = app.get_sum() assert True assert res == 42
9 10 11 12
def test_again(): print(app.data_file)
# it is now back to the original value
Monkey Patching functions
Fixtures and Mocking in Python
2
def run(x): return 2 * x
1
import aut
1
2 3 4
def test_a(): assert aut.run(7) == 14
5 6 7
def test_b(monkeypatch): monkeypatch.setattr('aut.run', lambda z: z)
8 9
assert aut.run(5) == 5
10 11 12
def test_c(): assert aut.run(10) == 20
Monkey Patching dictionary items
4
data = { 'name' : 'foo', 'age' : 42 }
1
import aut
1 2 3
2 3 4 5 6 7
def test_a(): assert aut.data == { 'name' : 'foo', 'age' : 42 }
8 9 10
def test_b(monkeypatch): monkeypatch.setitem(aut.data, 'name', 'bar')
11 12 13 14 15
assert aut.data == { 'name' : 'bar', 'age' : 42 }
16 17
def test_c():
14
Fixtures and Mocking in Python
assert aut.data == { 'name' : 'foo', 'age' : 42 }
18 19 20 21
Mocking a whole class 1
import json
2 3 4 5
class Thing(object): def data_file(): return "/corporate/fixed/path/data.json"
6
def get_sum(self): data_file = self.data_file() with open(data_file) as fh: data = json.load(fh) # ... result = data['x'] + data['y'] return result
7 8 9 10 11 12 13
1
{ "x": 19, "y": 23
2 3 4
}
1
import app
2 3 4 5 6 7 8
def test_sum(): app.Thing.data_file = lambda self: 'data.json' t = app.Thing() res = t.get_sum() assert True assert res == 42
Mocking input/output
15
Fixtures and Mocking in Python 1 2 3
def calc(): a = input("Type in a: ") b = input("Type in b: ")
4 5
print("The result is:", add(int(a), int(b)))
6 7 8
def add(x, y): return x+y
9 10 11
if __name__ == '__main__': calc()
The test: 1
import app
2 3 4
def test_app(): assert app.add(2, 3) == 5
Mocking input/output 1
import app
2 3 4 5
def test_calc(): input_values = ['19', '23'] output = []
6 7 8 9 10 11
def mock_input(s): output.append(s) return input_values.pop(0) app.input = mock_input app.print = lambda *s : output.append(s)
12 13
app.calc()
14 15 16 17 18 19
assert output == [ 'Type in a: ', 'Type in b: ', ('The result is:', 42), ]
16
Fixtures and Mocking in Python
Mocking random numbers • Mock the methods of the random module
Exercises Download zip file⁷ or clone repository using 1
git clone https://github.com/szabgab/slides.git
the files are in the directory. 1
slides/python-mocking/
Work in pairs • Navigator - Driver • Driver - Observer
Exercise: test login expiration 1
import time
2 3
TIMEOUT = 60*60*24*7
4 5 6 7
class MySystem(): def __init__(self): self.logged_in = 0
8 9 10 11 12 13
def login(self, name, password): resp = self.verify_user(name, password) if resp: self.logged_in = True self.seen()
14 15
return resp
16
⁷https://github.com/szabgab/slides
17
Fixtures and Mocking in Python 17 18
def seen(self): self.last_seen = time.time()
19 20 21
def is_logged_in(self): return self.logged_in and self.last_seen + TIMEOUT > time.time()
22 23 24 25 26
1
def verify_user(self, name, password): if name == 'foo' and password == 'secret': return True return False
from app import MySystem
2 3 4 5
def test_app(): s = MySystem() assert not s.is_logged_in()
6 7 8
assert not s.login('bar', 'secret') assert not s.is_logged_in()
9 10 11
assert s.login('foo', 'secret') assert s.is_logged_in()
12 13
# how to test the timeout?
Solution: test login expiration 1 2
from app import MySystem import time
3 4 5 6
def test_app(monkeypatch): s = MySystem() assert not s.is_logged_in()
7 8 9
assert not s.login('bar', 'secret') assert not s.is_logged_in()
10 11 12
assert s.login('foo', 'secret') assert s.is_logged_in()
13 14
now = time.time() + 60*60*24*7 + 1
18
Fixtures and Mocking in Python 15
19
monkeypatch.setattr('time.time', lambda : now)
16 17
assert not s.is_logged_in()
Exercise: Record e-mail sending Implement a registration for a Flask (or other) web application: Accept e-mail as input send e-mail with a code to the given address use that code to verify e-mail address. Without actually sending e-mails. 1 2
from flask import Flask, request import random
3 4 5
app = Flask(__name__) db = {}
6 7 8 9 10 11 12 13 14
@app.route('/', methods=['GET']) def home(): return '''
'''
15 16 17 18 19 20 21 22 23 24 25 26
@app.route('/register', methods=['POST']) def register(): email = request.form.get('email') code = str(random.random()) if db_save(email, code): html = 'here'.format(email=email, code \ = code) sendmail({'to': email, 'subject': 'Registration', 'html': html }) return 'OK' else: return 'FAILED'
27 28 29 30 31
@app.route('/verify//', methods=['GET']) def verify(email, code): if db_verify(email, code): sendmail({'to': email, 'subject': 'Welcome!', 'html': '' })
Fixtures and Mocking in Python 32 33 34
20
return 'OK' else: return 'FAILED'
35 36 37
def sendmail(data): pass
38 39 40 41 42 43
def db_save(email, code): if email in db: return False db[email] = code return True
44 45 46
def db_verify(email, code): return email in db and db[email] == code
Solution: Record e-mail sending 1 2
import app import re
3 4 5
def test_app(monkeypatch): aut = app.app.test_client()
6 7 8 9 10
rv = aut.get('/') assert rv.status == '200 OK' assert ' y else "No" print(result) # Yes
5 6 7 8
x = "12" y = "3" print("Yes" if x > y else "No") # No
9 10 11 12
x = "12" y = 3 print("Yes" if x > y else "No") # Yes ⁷⁰https://en.wikipedia.org/wiki/ASCII
84
Comparison and Boolean 13 14 15 16
x = 12 y = "3" print("Yes" if x > y else "No")
# No
In Python 2 please be careful and only compare the same types. Otherwise the result will look strange. 1 2 3 4
Yes No Yes No
In Python 3, comparing different types raises exception: 1 2 3 4 5 6
Yes No Traceback (most recent call last): File "examples/other/compare.py", line 11, in print("Yes" if x > y else "No") # Yes TypeError: '>' not supported between instances of 'str' and 'int'
Complex if statement with boolean operators • • • •
1 2
Boolean operators or Logical operators and or not
age = 16 name = "Foo"
3 4 5 6 7
if 0 < age and age 1000000
3 4 5 6
def check_salary(): salary += 1 return salary >= 1000
7 8 9 10
while True: if check_money() or check_salary(): print("I can live well")
Short circuit fixed 1 2
def check_money(): return money > 1000000
3 4 5 6
def check_salary(): salary += 1 return salary >= 1000
7 8 9 10
while True: has_good_money = check_money() has_good_salary = check_salary()
11 12 13
if has_good_money or has_good_salary: print("I can live well")
Does this value count as True or False?
Comparison and Boolean 1
x = 23
2 3 4
if x: print("23 is true")
5 6 7
if x != 0: print("23 is true")
8 9 10 11 12 13
y = 0 if y: print("0 is true") else: print("0 is false")
14 15 16 17 18
if y != 0: print("0 is true") else: print("0 is false")
19 20 21
# 23 is true # 0 is false
True and False values in Python • • • • • • •
None 0 ”” (empty string) False [] {} ()
Everything else is true.
90
Comparison and Boolean 1
values = [None, 0, "", False, [], (), {}, "0", True]
2 3 4 5 6 7
for v in values: if v: print("True value: ", v) else: print("False value: ", v)
8 9 10 11 12 13 14 15 16 17
# # # # # # # # #
False value: False value: False value: False value: False value: False value: False value: True value: True value:
None 0 False [] () {} 0 True
None is like undef or Null or Nill in other languages.
Incorrect use of conditions In your normal speach you could probably say something like “If status_code is 401 or 302, do something.”. Meaning status_cone can be either 401 or 302. If you tried to translate this into code directly you would write something like this:
1 2
if status_code == 401 or 302: pass
However, this is incorrect. This condition will always be true as this is actually same as if you wrote: if (status_code == 401) or (302) so it will compare status_code to 401, and it will separately check if 302 is True, but any number different from 0 is considered to be True so the above expression will always be True.
What you probably meant is this:
91
Comparison and Boolean 1 2
92
if status_code == 401 or status_code == 302: pass
Alternative way: An alternative way to achieve the same results would be though probbaly at this point we have not learned the “in” operator, nor lists (comma separated values in square brackets):
1 2
if status_code in [401, 302] pass
Exercise: compare numbers • Ask the user to enter two numbers and tell us which one is bigger.
Exercise: compare strings • Ask the user to enter two strings • Then ask the user to select if she wants to compare them based on ASCII or based on their length • Then tell us which one is bigger.
1 2 3 4 5 6
Input a string: (user types string and ENTER) Input another string: (user types string and ENTER) How to compare: 1) ASCII 2) Length (user types 1 or 2 and ENTER)
Solution: compare numbers
Comparison and Boolean 1 2
a_in = input("Please type in a whole number: ") b_in = input("Please type in another whole number: ")
3 4 5 6 7
if not a_in.isdecimal(): exit("First input was not a whole number") if not b_in.isdecimal(): exit("Second input was not a whole number")
8 9 10 11
a_num = float(a_in) b_num = float(b_in)
12 13 14 15 16 17 18
if a_num > b_num: print("First number is bigger") elif a_num < b_num: print("First number is smaller") else: print("They are equal")
Solution: compare strings 1 2 3 4 5 6
a_in = input("Please type in a string: ") b_in = input("Please type in another string: ") print("How to compare:") print("1) ASCII") print("2) Length") how = input()
7 8 9 10 11 12 13
if how == '1': first_is_bigger = a_in > b_in second_is_bigger = a_in < b_in elif how == '2': first_is_bigger = len(a_in) > len(b_in) second_is_bigger = len(a_in) < len(b_in)
14 15 16 17 18 19 20
if first_is_bigger: print("First number is bigger") elif second_is_bigger: print("First number is smaller") else: print("They are equal")
93
Strings Single quoted and double quoted strings In Python, just as in most of the programming languages you must put any free text inside a pair of quote characters. Otherwise Python will try to find meaning in the text. These pieces of texts are called “strings”. In Python you can put string between two single quotes: ‘’ or between two double quotes: “”. Which one, does not matter.
1 2
soup = "Spiced carrot & lentil soup" salad = 'Ceasar salad'
3 4 5
1 2
print(soup) print(salad)
Spiced carrot & lentil soup Ceasar salad
Long lines 1 2
text = "abc" "def" print(text)
3 4 5
other = "abcdef" print(other)
6 7 8 9
long_string = "one" "two" "three" print(long_string)
10 11
short_rows = "one" \
95
Strings 12 13 14
"two" \ "three" print(short_rows)
15 16 17
long_string = "first row second row third row" print(long_string)
18 19 20 21 22
1 2 3 4 5 6
shorter = "first row \ second row \ third row" print(shorter)
abcdef abcdef onetwothree onetwothree first row second row third row first row second row third row
Triple quoted strings (multiline) If you would like to create a string that spreads on multiple lines, there is a possibility to put the text between 3 quotes on both sides. Either 23 single-quotes or 23 double-quotes.
1 2 3
text = """first row second row third row"""
4 5
print(text)
Can spread multiple lines. 1 2 3
first row second row third row
96
Strings
String length (len) The len function returns the length of the string in number of characters.
1 2 3
line = "Hello World" hw = len(line) print(hw) # 11
4 5 6 7
text = """Hello World""" print(len(text))
# 12
String repetition and concatenation You might be used to the fact that you can only multiply numbers, but in python you can also “multiply” a string by a number. It is called repetition. In this example we have a string “Jar “ that we repeat twice. We can also add two strings to concatenate them together. I don’t think the repetition operator is used very often, but in one case it could come in very handy. When you are writing some text report and you’d like to add a long line of dashes that would be exactly the same length as your title.
1 2
name = 2 * 'Jar ' print(name)
# Jar Jar
3 4 5
full_name = name + 'Binks' print(full_name) # Jar Jar Binks
6 7 8 9 10
title = "We have some title" print(title) print('-' * len(title))
11 12 13
# We have some title # ------------------
97
Strings
A character in a string 1
text = "Hello World"
2 3 4
a = text[0] print(a)
# H
b = text[6] print(b)
# W
5 6 7
String slice (instead of substr) 1
text = "Hello World"
2 3 4
b = text[1:4] print(b)
# ell
print(text[2:]) print(text[:2])
# llo World # He
5 6 7 8 9 10 11
start = 1 end = 4 print(text[start:end])
# ell
Change a string In Python strings are “immutable”, meaning you cannot change them. You can replace a whole string in a variable, but you cannot change it. In the following example we wanted to replace the 3rd character (index 2), and put “Y” in place. This raised an exception
98
Strings 1 2
text = "abcd" print(text)
# abcd
3 4
text[2] = 'Y'
5 6 7
1 2 3 4 5
print("done") print(text)
abcd Traceback (most recent call last): File "string_change.py", line 4, in text[2] = 'Y' TypeError: 'str' object does not support item assignment
Replace part of a string
• Strings in Python are immutable - they never change.
How to change a string 1 2
text = "abcd" print(text)
# abcd
3 4 5
text = text[:2] + 'Y' + text[3:] print(text) # abYd
String copy
99
Strings 1 2
text = "abcd" print(text)
# abcd
3 4 5
text = text + "ef" print(text) # abcdef
6 7 8 9 10 11
other = text print(other) text = "xyz" print(text) print(other)
# abcdef # xyz # abcdef
When assigning a variable pointing to a string, the new variable is pointing to the same string.. If we then assign some other string to either of the variables, then they will point to two different strings.
String functions and methods (len, upper, lower) 1 2
a = "xYz" print(len(a))
# 3
b = a.upper() print(b) print(a) print(a.lower())
# XYZ # xYz # xyz
3 4 5 6 7
- immutable!
• Type dir(“”) in the REPL to get the list of string methods. • List of built-in functions⁷¹. • List of string methods⁷².
index in string
⁷¹http://docs.python.org/library/functions.html ⁷²http://docs.python.org/library/string.html
100
Strings 1 2 3 4 5
1 2 3 4 5 6
text = "The black cat climbed print(text.index("bl")) # print(text.index("The")) # print(text.index("the")) # print(text.index("dog"))
the green tree." 4 0 22
4 0 Traceback (most recent call last): File "examples/strings/index.py", line 6, in print a.index("dog") # -1 ValueError: substring not found
index in string with range 1 2 3
text = "The black cat climbed the green tree." print(text.index("c")) # 7 print(text.index("c", 8)) # 10
4 5 6
1 2 3 4 5 6 7
print(text.index("gr", 8)) print(text.index("gr", 8, 16))
# 26
7 10 26 Traceback (most recent call last): File "examples/strings/index2.py", line 8, in print a.index("gr", 8, 16) ValueError: substring not found
rindex in string with range
101
Strings 1 2 3 4
text = "The black cat climbed the print(text.rindex("c")) # print(text.rindex("c", 8)) # print(text.rindex("c", 8, 13)) #
green tree." 14 14 10
5 6 7
1 2 3 4 5 6 7 8
print(text.rindex("gr", 8)) # 26 print(text.rindex("gr", 8, 16))
14 14 10 26 Traceback (most recent call last): File "examples/strings/rindex.py", line 10, in print(a.rindex("gr", 8, 16)) ValueError: substring not found
find in string Alternatively use find and rfind that will return -1 instead of raising an exception. 1 2 3 4
text = "The black cat climbed the green tree." print(text.find("bl")) # 4 print(text.find("The")) # 0 print(text.find("dog")) # -1
5 6 7
print(text.find("c")) print(text.find("c", 8))
# 7 # 10
8 9 10
print(text.find("gr", 8)) print(text.find("gr", 8, 16))
# 26 # -1
11 12 13
print(text.rfind("c", 8))
# 14
Find all in the string Later, when we learned loops.
Strings
in string Check if a substring is in the string? 1 2 3
txt = "hello world" if "wo" in txt: print('found wo')
4 5 6 7 8
1 2
if "x" in txt: print("found x") else: print("NOT found x") found wo NOT found x
index if in string 1 2
sub = "cat" txt = "The black cat climbed the green tree"
3 4 5 6
if sub in txt: loc = txt.index(sub) print(sub + " is at " + str(loc))
7 8 9 10 11
sub = "dog" if sub in txt: loc = txt.index(sub) print(sub + " is at " + str(loc))
12 13
# cat is at 10
Encodings: ASCII, Windows-1255, Unicode • • • •
ASCII⁷³ Hebrew Character⁷⁴ Windows-1255⁷⁵ Unicode (UTF-8)⁷⁶
⁷³https://en.wikipedia.org/wiki/ASCII ⁷⁴https://en.wikipedia.org/wiki/Hebrew_character ⁷⁵https://en.wikipedia.org/wiki/Windows-1255 ⁷⁶https://en.wikipedia.org/wiki/Unicode
102
103
Strings
raw strings 1 2
# file_a = "c:\Users\Foobar\readme.txt" # print(file_a)
3 4 5 6 7 8 9 10
# Python2: eadme.txtFoobar # Python3: # File "examples/strings/raw.py", line 6 # file_a = "c:\Users\Foobar\readme.txt" # ^ # SyntaxError: (unicode error) 'unicodeescape' codec # can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
11 12 13 14
file_b = "c:\\Users\\Foobar\\readme.txt" print(file_b) # c:\Users\Foobar\readme.txt
15 16 17
file_c = r"c:\Users\Foobar\readme.txt" print(file_c) # c:\Users\Foobar\readme.txt
18 19 20
text = r"text \n \d \s \ and more" print(text) # text \n \d \s \ and more
Escape sequences are kept intact and not escaped. Used in regexes.
ord • ord⁷⁷
1 2 3 4 5
print( print( print( print( print(
ord('a') ) ord('=') ) ord('\r') ) ord('\n') ) ord(' ') )
# # # # #
97 61 13 10 32
print( print( print( print(
ord('á') ord('ó') ord('�') ord('�')
# # # #
225 243 1488 1571
6 7 8 9 10
) ) ) )
Hungraian Hebrew alef Arabic/Farsi
⁷⁷https://docs.python.org/3/library/functions.html#ord
104
Strings 11 12 13
print( ord('α') ) print( ord('�') ) print( ord('�') )
# 945 Greek # 12623 Korean # 128520
ord in a file 1
import sys
2 3
filename = sys.argv[1]
4 5 6
with open(filename) as fh: content = fh.read()
7 8 9
for c in content: print(ord(c))
chr - number to character • chr⁷⁸
1 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
for i in range(32, 126): print( i, chr(i) )
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
! " # $ % & ' ( ) * + , . ⁷⁸https://docs.python.org/3/library/functions.html#chr
Strings 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/ 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y
105
Strings 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
106
90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w 120 x 121 y 122 z 123 { 124 | 125 }
Exercise: one string in another string Write script that accepts two strings and tells if one of them can be found in the other and where?
Strings
107
Exercise: to ASCII CLI Write script that gets a character on the command line and prints out the ascii code of it. Maybe even: Write script that gets a string on the command line and prints out the ascii code of each character.
Exercise: from ASCII CLI Write script that accepts a number on the command line and prints the character represented by that number.
Solution: one string in another string 1
import sys
2 3 4
if len(sys.argv) != 3: exit(f"Usage: {sys.argv[0]} short-STRING long-STRING")
5 6 7
string = sys.argv[1] text = sys.argv[2]
8 9 10 11 12 13
if string in text: loc = text.index(string) print(string, "can be found in ", text, "at", loc) else: print(string, "can NOT be found in ", text)
Solution: compare strings
Strings 1 2 3 4
mode = input("Mode of comparision: [length|ascii]") if mode != "length" and mode != "ascii": print("Not good") exit()
5 6 7
str1 = input("String 1:") str2 = input("String 2:")
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
if mode == "length": if len(str1) > len(str2): print("First is longer") elif len(str1) < len(str2): print("Second is longer") else: print("They are of equal length") elif mode == "ascii": if str1 > str2: print("First is later in the ABC order") elif str1 < str2: print("Second is later in the ABC order") else: print("The strings are equal")
Solution: to ASCII CLI 1
import sys
2 3 4
if len(sys.argv) != 2: exit(f"Usage: {sys.argv[0]} CHARACTER")
5 6
print( ord( sys.argv[1]) )
1
import sys
2 3 4
if len(sys.argv) != 2: exit(f"Usage: {sys.argv[0]} STRING")
5 6 7
for cr in sys.argv[1]: print( ord( cr ) )
Solution: from ASCII CLI
108
Strings 1
import sys
2 3 4
if len(sys.argv) != 2: exit(f"Usage: {sys.argv[0]} NUMBER")
5 6
print( chr( int(sys.argv[1]) ) )
109
Loops Loops: for-in and while • for in - to iterate over a well defined list of values. (characters, range of numbers, shopping list, etc.) • while - repeate an action till some condition is met. (or stopped being met)
for-in loop on strings 1 2 3
1 2 3 4 5
txt = 'hello world' for ch in txt: print(ch)
h e l l o
6 7 8 9 10 11
w o r l d
for-in loop on list 1 2
for fruit in ["Apple", "Banana", "Peach", "Orange", "Durian", "Papaya"]: print(fruit)
Loops 1 2 3 4 5 6
Apple Banana Peach Orange Durian Papaya
for-in loop on range 1 2
1 2 3 4
for ix in range(3, 7): print(ix)
3 4 5 6
Iterable, iterator • iterable⁷⁹
for in loop with early end using break 1 2 3 4 5
txt = 'hello world' for ch in txt: if ch == ' ': break print(ch)
6 7
print("Here")
⁷⁹https://docs.python.org/3/glossary.html#term-iterable
111
Loops 1 2 3 4 5 6
h e l l o Here
for in loop skipping parts using continue 1 2 3 4 5
1 2 3 4 5 6 7 8 9 10
txt = 'hello world' for ch in txt: if ch == ' ': continue print(ch)
h e l l o w o r l d
for in loop with break and continue 1 2 3 4 5 6 7 8
txt = 'hello world' for cr in txt: if cr == ' ': continue if cr == 'r': break print(cr) print('DONE')
112
Loops 1 2 3 4 5 6 7 8
h e l l o w o DONE
while loop 1
import random
2 3 4 5 6
total = 0 while total = 0: print(total) total += random.randrange(20)
7 8
print("done")
1
... 1304774 1304779 1304797 ^C1304803 Traceback (most recent call last): File "while_infinite.py", line 5, in print(total) KeyboardInterrupt
2 3 4 5 6 7 8 9
• Don’t do this! • Make sure there is a proper end-condition. (exit-condition) • Use Ctrl-C to stop it
While with complex expression 1 2
import random random.seed(0)
3 4 5 6 7
total = 0 while (total < 10000000) and (total % 17 != 1) and (total ** 2 % 23 != 7): print(total) total += random.randrange(20)
8 9
print("done")
114
Loops 1 2 3 4 5 6 7 8 9
0 12 25 26 34 50 65 77 done
While with break 1 2
import random random.seed(0)
3 4 5 6 7
total = 0 while total < 10000000: print(total) total += random.randrange(20)
8 9 10
if total % 17 == 1: break
11 12 13
if total ** 2 % 23 == 7: break
14 15
1 2 3 4 5 6 7 8 9
print("done")
0 12 25 26 34 50 65 77 done
While True
115
Loops 1 2
import random random.seed(0)
3 4 5 6 7
total = 0 while True: print(total) total += random.randrange(20)
8 9 10
if total >= 10000000: break
11 12 13
if total % 17 == 1: break
14 15 16
if total ** 2 % 23 == 7: break
17 18
1 2 3 4 5 6 7 8 9
print("done")
0 12 25 26 34 50 65 77 done
Duplicate input call 1
id_str = input("Type in your ID: ")
2 3 4
while len(id_str) != 9: id_str = input("Type in your ID")
5 6
print("Your ID is " + id_str)
Eliminate duplicate input call
116
Loops 1 2 3 4
117
while True: id_str = input("Type in your ID: ") if len(id_str) == 9: break
5 6
print("Your ID is " + id_str)
do while loop There is no do ... while in Python but we can write code like this to have similar effect. 1 2 3 4 5
while True: answer = input("What is the meaning of life? ") if answer == '42': print("Yeeah, that's it!") break
6 7
print("done")
while with many continue calls 1 2
while True: line = get_next_line()
3 4 5
if last_line: break
6 7 8
if line_is_empty: continue
9 10 11
if line_has_an_hash_at_the_beginning: # # continue
12 13 14
if line_has_two_slashes_at_the_beginning: # // continue
15 16
do_the_real_stuff
Break out from multi-level loops Not supported in Python. “If you feel the urge to do that, your code is probably too complex. Create functions!”
118
Loops
Exit vs return vs break and continue • • • •
exit will stop your program no matter where you call it. return will return from a function (it will stop the specific function only) break will stop the current “while” or “for” loop continue will stop the current iteration of the current “while” or “for” loop
Exercise: Print all the locations in a string Given a string like “The black cat climbed the green tree.”, print out the location of every “c” charcater. Expected: 1 2 3
7 10 14
Exercise: Number guessing game Level 0 • Using the random module the computer “thinks” about a whole number between 1 and 20. • The user has to guess the number. After the user types in the guess the computer tells if this was bigger or smaller than the number it generated, or if was the same. • The game ends after just one guess. Level 1 • The user can guess several times. The game ends when the user guessed the right number. Level 2 • If the user hits ‘x’, we leave the game without guessing the number. Level 3 • If the user presses ‘s’, show the hidden value (cheat) Level 4
119
Loops
• Soon we’ll have a level in which the hidden value changes after each guess. In oredr to make that mode easier to track and debug, first we would like to have a “debug mode”. • If the user presses ‘d’ the game gets into “debug mode”: the system starts to show the current number to guess every time, just before asking the user for new input. • Pressing ‘d’ again turns off debug mode. (It is a toggle each press on “d” changes the value to to the other possible value.) Level 5 • The ‘m’ button is another toggle. It is called ‘move mode’. When it is ‘on’, the hidden number changes a little bit after every step (+/-2). Pressing ‘m’ again will turn this feature off. Level 6 • Let the user play several games. • Pressing ‘n’ will skip this game and start a new one. Generates a new number to guess.
Exercise: Count unique characters Given a string on the command line, count how many differnt characters it has. 1 2
python count_unique.py abcdaaa 4
Exercise: Convert for-loop to while-loop Given a for-loop as in the following code, convert it to be using a while-loop. 1 2
for ix in range(3, 17, 3): print(ix)
Solution: Print all the locations in a string When you start thinking about this exercise, you probably call loc = text.find("c") and then you wonder how could you find the next element. After a while it might occur to you that the find method can get a second parameter to set the location where we start the search. Basically you need to call loc = text.find("c", loc + 1) but that looks strange. How can you use loc (as a paramter of the function) and also assign to it. However programming languages don’t have a problem with this as the assignment happens after the right-hand-side was fully executed.
120
Loops
The problem that now you have two different calls to find. The first one and all the subsequent calls. How could we merge the two calls? The trick is that you need to have an initial value for the loc variable and it has to be -1, so when we call find for the first time, it will start from the first character (index 0).
1 2 3 4 5 6 7
text = "The black cat climbed the green tree." loc = -1 while True: loc = text.find("c", loc+1) if loc == -1: break print(loc)
Using an additinal variable might make the code easier to read:
1 2 3 4 5 6 7 8
text = "The black cat climbed the green tree." start = 0 while True: loc = text.find("c", start) if loc == -1: break print(loc) start = loc + 1
Solution 1 for Number Guessing
121
Loops 1
import random
2 3 4 5 6
hidden = random.randrange(1, 201) while True: user_input = input("Please enter your guess: ") print(user_input)
7 8 9 10 11
guess = int(user_input) if guess == hidden: print("Hit!") break
12 13 14 15 16
if guess < hidden: print("Your guess is too low") else: print("Your guess is too high")
Solution 2 for Number Guessing (x) The main trick is that you check for the input being “x” before you try to convert it to an integer.
1
import random
2 3 4 5 6
hidden = random.randrange(1, 201) while True: user_input = input("Please enter your guess[x]: ") print(user_input)
7 8 9 10
if user_input == 'x': print("Sad to see you leaving early") exit()
11 12 13 14 15
guess = int(user_input) if guess == hidden: print("Hit!") break
16 17 18
if guess < hidden: print("Your guess is too low")
122
Loops 19 20
else: print("Your guess is too high")
Solution 3 for Number Guessing (s) 1
import random
2 3 4 5 6
hidden = random.randrange(1, 201) while True: user_input = input("Please enter your guess [x|s|d]: ") print(user_input)
7 8 9 10
if user_input == 'x': print("Sad to see you leaving early") exit()
11 12 13 14
if user_input == 's': print("The hidden value is ", hidden) continue
15 16 17 18 19
guess = int(user_input) if guess == hidden: print("Hit!") break
20 21 22 23 24
if guess < hidden: print("Your guess is too low") else: print("Your guess is too high")
Solution for Number Guessing (debug) One important thing is to remember that you can create a toggle by just calling not on a boolean variable every time you’d like to flip the switch. The other one is that flipping the switch (pressing d) and printing the current value because debug mode is on, are two separate operations that are not directly related and so they can be implemented separately.
Loops 1
import random
2 3 4 5 6 7
hidden = random.randrange(1, 201) debug = False while True: if debug: print("Debug: ", hidden)
8 9 10
user_input = input("Please enter your guess [x|s|d]: ") print(user_input)
11 12 13 14
if user_input == 'x': print("Sad to see you leaving early") exit()
15 16 17 18
if user_input == 's': print("The hidden value is ", hidden) continue
19 20 21 22
if user_input == 'd': debug = not debug continue
23 24 25 26 27
guess = int(user_input) if guess == hidden: print("Hit!") break
28 29 30 31 32
if guess < hidden: print("Your guess is too low") else: print("Your guess is too high")
Solution for Number Guessing (move)
123
Loops 1
import random
2 3 4 5 6 7 8
hidden = random.randrange(1, 201) debug = False move = False while True: if debug: print("Debug: ", hidden)
9 10 11 12
if move: mv = random.randrange(-2, 3) hidden = hidden + mv
13 14 15
user_input = input("Please enter your guess [x|s|d|m]: ") print(user_input)
16 17 18 19
if user_input == 'x': print("Sad to see you leaving early") exit()
20 21 22 23
if user_input == 's': print("The hidden value is ", hidden) continue
24 25 26 27
if user_input == 'd': debug = not debug continue
28 29 30 31
if user_input == 'm': move = not move continue
32 33 34 35 36
guess = int(user_input) if guess == hidden: print("Hit!") break
37 38 39 40 41
if guess < hidden: print("Your guess is too low") else: print("Your guess is too high")
124
125
Loops
Solution for Number Guessing (multi-game) 1
import random
2 3 4 5 6 7 8 9 10
debug = False move = False while True: print("\nWelcome to another Number Guessing game") hidden = random.randrange(1, 201) while True: if debug: print("Debug: ", hidden)
11 12 13 14
if move: mv = random.randrange(-2, 3) hidden = hidden + mv
15 16 17
user_input = input("Please enter your guess [x|s|d|m|n]: ") print(user_input)
18 19 20 21
if user_input == 'x': print("Sad to see you leaving early") exit()
22 23 24 25
if user_input == 's': print("The hidden value is ", hidden) continue
26 27 28 29
if user_input == 'd': debug = not debug continue
30 31 32 33
if user_input == 'm': move = not move continue
34 35 36 37
if user_input == 'n': print("Giving up, eh?") break
38 39 40
guess = int(user_input) if guess == hidden:
126
Loops
print("Hit!") break
41 42 43 44 45 46 47
if guess < hidden: print("Your guess is too low") else: print("Your guess is too high")
Solution: Count unique characters 1
import sys
2 3 4
if len(sys.argv) != 2: exit("Need a string to count")
5 6
text = sys.argv[1]
7 8 9 10 11
unique = '' for cr in text: if cr not in unique: unique += cr
12 13
print(len(unique))
The above solution works, but there is a better solution using sets that we have not learned yet. Nevertheless, let me show you that solution:
1
import sys
2 3 4
if len(sys.argv) != 2: exit("Need a string to count")
5 6
text = sys.argv[1]
7 8
set_of_chars = set(text)
9 10
print(len(set_of_chars))
Loops
Solution: Convert for-loop to while-loop 1 2 3 4
ix = 3 while ix 10} was born {age} years ago.") {name:>10} was born {age:>10} years ago.")
10 11 12
print(f"PI is '{pi:.3}'.") print(f"PI is '{pi:.3f}'.")
# number of digits (defaults n = number) # number of digits after decimal point
13 14 15
1 2 3 4 5 6 7 8
print(f"Area is {pi * r ** 2}") print(f"Area is {pi * r ** 2:.3f}")
The user Foo Bar was born 42.12 years ago. The user Foo Bar was born 42.12 years ago. The user Foo Bar was born 42.12 years ago. The user Foo Bar was born 42.12 years ago. PI is '3.14'. PI is '3.142'. Area is 12.566370614359172 Area is 12.566
printf using old %-syntax This slides is here only as a historical page. It is recommended to use the format method!
133
Formatted printing 1 2 3 4 5 6 7
v = 65 print("" % v) print("" % v) print("" % v) print("" % v) print("" % v) print("" % v)
# # # # # #
< 65>
Format braces, bracket, and parentheses These are just some extreme special cases. Most people won’t need to know about them. To print { include {{. To print } include }}. 1
print("{{{}}}".format(42))
# {42}
2 3
print("{{ {} }}".format(42))
# { 42 }
4 5
print("[{}] ({})".format(42, 42))
# [42] (42)
6 7
print("%{}".format(42))
# %42
Anything that is not in curly braces will be formatted as they are.
Examples using format with attributes of objects This is also a rather strange example, I don’t think I’d use it in real code. 1
import sys
2 3 4
1 2
print("{0.executable}".format(sys)) print("{system.argv[0]}".format(system = sys))
/home/gabor/venv3/bin/python formatted_attributes.py
raw f-strings
134
Formatted printing 1 2 3 4
1 2 3
name="foo" print(r"a\nb {name}") print(rf"a\nb {name}") print(fr"a\nb {name}")
a\nb {name} a\nb foo a\nb foo
# this is better (for vim)
Lists Anything can be a list • Comma separated values • In square brackets • Can be any value, and a mix of values: Integer, Float, Boolean, None, String, List, Dictionary, … • But usually they are of the same type: • Distances of astronomical objects • Chemical Formulas • Filenames • Names of devices • Objects describing attributes of a network device. • Actions to do on your data.
1 2 3
1 2
stuff = [42, 3.14, True, None, "Foo Bar", ['another', 'list'], {'a': 'Dictionary', '\ language' : 'Python'}] print(stuff)
[42, 3.14, True, None, 'Foo Bar', ['another', 'list'], {'a': 'Dictionary', 'language\ ': 'Python'}]
Any layout • Layout is flexible • Trailing comma is optional. It does not disturb us. Nor Python.
136
Lists 1 2 3 4 5 6 7 8 9 10 11 12 13
1 2
more_stuff = [ 42, 3.14, True, None, "Foo Bar", ['another', 'list'], { 'a': 'Dictionary', 'language' : 'Python', }, ] print(more_stuff) [42, 3.14, True, None, 'Foo Bar', ['another', 'list'], {'a': 'Dictionary', 'language\ ': 'Python'}]
Lists • Access single element: [index] • Access a sublist: [start:end] • Creates a copy of that sublist 1
planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn']
2 3 4
print(planets) # ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn'] print(len(planets)) # 6
5 6 7 8
print(planets[0]) print(type(planets[0])) print(planets[3])
# Mercury # # Mars
print(planets[0:1]) print(type(planets[0:1])) print(planets[0:2]) print(planets[1:3])
# # # #
print(planets[2:]) print(planets[:3])
# ['Earth', 'Mars', 'Jupiter', 'Saturn'] # ['Mercury', 'Venus', 'Earth']
print(planets[:]) ']
# ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn\
9 10 11 12 13
['Mercury']
['Mercury', 'Venus'] ['Venus', 'Earth']
14 15 16 17 18 19
137
Lists
List slice with steps • List slice with step: [start:end:step]
1
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
2 3
print(letters[::])
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
print(letters[::1])
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
print(letters[::2])
# ['a', 'c', 'e', 'g', 'i']
print(letters[1::2])
# ['b', 'd', 'f', 'h', 'j']
print(letters[2:8:2])
# ['c', 'e', 'g']
print(letters[1:20:3])
# ['b', 'e', 'h']
4 5 6 7 8 9 10 11 12 13
Change a List 1 2 3 4
fruits = ['apple', 'banana', 'peach', 'strawberry'] print(fruits) # ['apple', 'banana', 'peach', 'strawberry'] fruits[0] = 'orange' print(fruits) # ['orange', 'banana', 'peach', 'strawberry']
5 6 7 8
fruits[1:3] = ['grape', 'kiwi'] print(fruits) # ['orange', 'grape', 'kiwi', 'strawberry']
9 10 11
fruits[1:3] = ['mango'] print(fruits) # ['orange', 'mango', 'strawberry']
12 13 14
fruits[1:2] = ["banana", "peach"] print(fruits) # ['orange', 'banana', 'peach', 'strawberry']
Lists 1
138
fruits = ['orange', 'mango', 'strawberry']
2 4
fruits[1:2] = ["banana", "peach"] print(fruits) # ['orange', 'banana', 'peach', 'strawberry']
1
fruits = ['orange', 'mango', 'strawberry']
3
2 3 4
fruits[1] = ["banana", "peach"] print(fruits) # ['orange', ['banana', 'peach'], 'strawberry']
• Unlike strings, lists are mutable. You can change the content of a list by assigning values to its elements. • You can use the slice notation to change several elements at once. • You can even have different number of elements in the slice and in the replacement. This will also change the length of the array.
Change with steps 1 2
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] print(numbers) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
3 4 5
numbers[1::2] = [0, 0, 0, 0, 0, 0] print(numbers) # [1, 0, 3, 0, 5, 0, 7, 0, 9, 0, 11, 0]
List assignment and list copy 1 2 3 4 5
x = ['apple', 'bob', 'cat', 'drone'] y = x x[0] = 'qqrq' print(x) # ['qqrq', 'bob', 'cat', 'drone'] print(y) # ['qqrq', 'bob', 'cat', 'drone']
• There is one list in the memory and two pointers to it. • If you really want to make a copy the pythonic way is to use the slice syntax. • It creates a shallow copy.
139
Lists 1 2
x = ['apple', 'bob', 'cat', 'drone'] y = x[:]
3 4
x[0] = 'qqrq'
5 6 7
print(x) print(y)
# ['qqrq', 'bob', 'cat', 'drone'] # ['apple', 'bob', 'cat', 'drone']
Shallow vs. Deep copy of lists 1 2 3 4
x = ['apple', ['cat', 'dog'], 'banana'] print(x) # ['apple', ['cat', 'dog'], 'banana'] print(x[0]) # apple print(x[1][0]) # cat
5 6
y = x[:]
7 8 9
x[0] = 'kiwi' x[1][0] = 'mouse'
10 11 12
1
print(x) print(y)
# ['kiwi', ['mouse', 'dog'], 'banana'] # ['apple', ['mouse', 'dog'], 'banana']
from copy import deepcopy
2 3 4 5 6
x = ['apple', ['cat', 'dog'], 'banana'] print(x) # ['apple', ['cat', 'dog'], 'banana'] print(x[0]) # apple print(x[1][0]) # cat
7 8 9 10
y = deepcopy(x) x[0] = 'kiwi' x[1][0] = 'mouse'
11 12 13
print(x) print(y)
join
# ['kiwi', ['mouse', 'dog'], 'banana'] # ['apple', ['cat', 'dog'], 'banana']
140
Lists 1
fields = ['one', 'two and three', 'four', 'five']
2 3 4
together = ':'.join(fields) print(together) # one:two and three:four:five
5 6 7
together = ' '.join(fields) print(together) # one two and three four five
8 9 10
mixed = ' -= '.join(fields) print(mixed) # one -= two and three -= four -= five
11 12 13
another = ''.join(fields) print(another) # onetwo and threefourfive
join list of numbers 1 2 3 4
a = ["x", "2", "y"] b = ["x", 2, "y"] print(":".join(a)) # print ":".join(b)
# x:2:y # TypeError: sequence item 1: expected string, int found
5 6 7
# convert elements to string using map print(":".join( map(str, b) )) # x:2:y
8 9 10 11
# convert elements to string using list comprehension print(":".join( str(x) for x in b )) # x:2:y
split • Special case: To split a string to its characters: Use the list() function. • Split using more than one splitter: use re.split
Lists 1 2
words = "ab:cd::ef".split(':') print(words) # ['ab', 'cd', '', 'ef']
3 4 5 6
# special case: split by spaces names = "foo bar baz".split() print(names) # ['foo', 'bar', 'baz']
7 8 9 10
# special case: split to characters chars = list("ab cd") print(chars) # ['a', 'b', ' ', 'c', 'd']
for loop on lists 1 2 3
1 2 3 4
things = ['apple', 'banana', 'peach', 42] for var in things: print(var)
apple banana peach 42
in list Check if the value is in the list? 1 2 3
words = ['apple', 'banana', 'peach', '42'] if 'apple' in words: print('found apple')
4 5 6 7 8
if 'a' in words: print('found a') else: print('NOT found a')
9 10 11 12 13 14
if 42 in words: print('found 42') else: print('NOT found 42')
141
Lists 15 16 17
# found apple # NOT found a # NOT found 42
Where is the element in the list 1 2
words = ['cat', 'dog', 'snake', 'camel'] print(words.index('snake'))
3 4
print(words.index('python'))
1
2 Traceback (most recent call last): File "examples/lists/index.py", line 6, in print(words.index('python')) ValueError: 'python' is not in list
2 3 4 5
Index improved 1
words = ['cat', 'dog', 'snake', 'camel']
2 3 4 5
name = 'snake' if name in words: print(words.index(name))
6 7 8 9
name = 'python' if name in words: print(words.index(name))
. insert][].insert
142
143
Lists 1 2
words = ['apple', 'banana', 'cat'] print(words) # ['apple', 'banana', 'cat']
3 4 5
words.insert(2, 'zebra') print(words) # ['apple', 'banana', 'zebra', 'cat']
6 7 8
words.insert(0, 'dog') print(words) # ['dog', 'apple', 'banana', 'zebra', 'cat']
9 10 11 12
# Instead of this, use append (next slide) words.insert(len(words), 'olifant') print(words) # ['dog', 'apple', 'banana', 'zebra', 'cat', 'olifant']
. append][].append 1 2
names = ['Foo', 'Bar', 'Zorg', 'Bambi'] print(names) # ['Foo', 'Bar', 'Zorg', 'Bambi']
3 4 5
names.append('Qux') print(names) # ['Foo', 'Bar', 'Zorg', 'Bambi', 'Qux']
. remove][].remove 1 2
names = ['Joe', 'Kim', 'Jane', 'Bob', 'Kim'] print(names) # ['Joe', 'Kim', 'Jane', 'Bob', 'Kim']
3 4 5
print(names.remove('Kim')) print(names)
# None # ['Joe', 'Jane', 'Bob', 'Kim']
6 7 8 9 10 11
print(names.remove('George')) # Traceback (most recent call last): # File "examples/lists/remove.py", line 9, in # print(names.remove('George')) # None # ValueError: list.remove(x): x not in list
144
Lists
Remove first element from a list given by its value. Throws an exception if there is no such element in the list.
. pop]Remove element by index [].pop 1 2
planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter'] print(planets) # ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter']
3 4 5 6
third = planets.pop(2) print(third) print(planets)
# Earth # ['Mercury', 'Venus', 'Mars', 'Jupiter']
last = planets.pop() print(last) print(planets)
# Jupiter # ['Mercury', 'Venus', 'Mars']
7 8 9 10 11 12
# planets.pop(4)
# IndexError: pop index out of range
jupyter_landers = [] # jupyter_landers.pop()
# IndexError: pop from empty list
13 14 15
Remove and return the last element of a list. Throws an exception if the list was empty.
Remove first element of list To remove an element by its index, use the slice syntax:
145
Lists 1
names = ['foo', 'bar', 'baz', 'moo']
2 3 4 5
first = names.pop(0) print(first) # foo print(names) # ['bar', 'baz', 'moo']
Remove several elements of list by index To remove an element by its index, use the slice syntax:
1
names = ['foo', 'bar', 'baz', 'moo', 'qux']
2 3 4
names[2:4] = [] print(names) # ['foo', 'bar', 'qux']
Use list as a queue 1 2
a_queue = [] print(a_queue)
3 4 5
a_queue.append('Moo') print(a_queue)
6 7 8
a_queue.append('Bar') print(a_queue)
9 10 11 12
1 2 3 4 5
first = a_queue.pop(0) print(first) print(a_queue) [] ['Moo'] ['Moo', 'Bar'] Moo ['Bar']
Queue using deque from collections
146
Lists 1
from collections import deque
2 3 4
# items = deque([]) items = deque(['foo', 'bar'])
5 6 7
print(type(items)) print(items)
# # deque(['foo', 'bar'])
8 9 10 11
items.append('zorg') print(items) # deque(['foo', 'bar', 'zorg']) print(len(items)) # 3
12 13 14
items.append('zorg') print(items) # deque(['foo', 'bar', 'zorg', 'zorg'])
15 16 17 18
nxt = items.popleft() print(nxt) # 'foo' print(items) # deque(['bar', 'zorg', 'zorg'])
19 20
print(len(items))
# 3
21 22 23 24 25
if items: print("The queue has items") else: print("The queue is empty")
• • • • •
.append .popleft len() number of elements if q: to see if it has elements or if it is empty dequeue⁸⁰
Fixed size queue
⁸⁰https://docs.python.org/3/library/collections.html#collections.deque
147
Lists 1
from collections import deque
2 3 4 5
queue = deque([], maxlen = 3) print(len(queue)) # 0 print(queue.maxlen) # 3
6 7 8 9 10
queue.append("Foo") queue.append("Bar") queue.append("Baz") print(queue)
# deque(['Foo', 'Bar', 'Baz'], maxlen=3)
queue.append("Zorg") print(queue)
# Automatically removes the left-most (first) element # deque(['Bar', 'Baz', 'Zorg'], maxlen=3)
11 12 13
List as a stack 1
stack = []
2 3 4 5 6 7 8
stack.append("Joe") print(stack) stack.append("Jane") print(stack) stack.append("Bob") print(stack)
9 10 11 12 13 1 2 3 4 5 6 7 8 9
while stack: name = stack.pop() print(name) print(stack) ['Joe'] ['Joe', 'Jane'] ['Joe', 'Jane', 'Bob'] Bob ['Joe', 'Jane'] Jane ['Joe'] Joe []
stack with deque
Lists 1 2
148
from collections import deque stack = deque()
3 4 5 6
stack.append("Joe") stack.append("Jane") stack.append("Bob")
7 8 9 10
while stack: name = stack.pop() print(name)
11 12 13 14
# Bob # Jane # Joe
Exercies: Queue The application should manage a queue of people. • It will prompt the user for a new name by printing :, the user can type in a name and press ENTER. The app will add the name to the queue. • If the user types in “n” then the application will remove the first name from the queue and print it. • If the user types in “x” then the application will print the list of users who were left in the queue and it will exit. • If the user types in “s” then the application will show the current number of elements in the queue. 1 2 3 4
: : : :
5 6
:
7 8 9
: :
10 11
:
12 13 14
:
Foo Bar Moo n next is Foo n next is Bar Peter n next is Moo n next is Peter n the queue is empty
Lists
Exercise: Stack Implement a Reverse Polish Calculator 1 2 3 4 5 6 7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
2 3 4 + * = 14
x = eXit, s = Show, [+-*/=] :23 :19 :7 :8 :+ :3 ::/ :s [23.0, -0.631578947368421] :+ := 22.36842105263158 :s [] :x
Exercise: MasterMind Implement the MasterMind game. The computer “thinks” a number with 4 different digits. You guess which digits. For every digit that matched both in value, and in location the computer gives you a *. For every digit that matches in value, but not in space the computer gives you a +. Try to guess the given number in as few guesses as possible.
149
150
Lists 1 2 3
Computer: 2153 You: 2467 You: 2715
* *++
Solution: Queue with list 1
queue = []
2 3 4 5
while True: inp = input(":") inp = inp.rstrip("\n")
6 7 8 9 10
if inp == 'x': for name in queue: print(name) exit()
11 12 13 14
if inp == 's': print(len(queue)) continue
15 16 17 18 19 20 21
if inp == 'n': if len(queue) > 0: print("next is {}".format(queue.pop(0))) else: print("the queue is empty") continue
22 23
queue.append(inp)
Solution: Queue with deque
151
Lists 1
from collections import deque
2 3
queue = deque()
4 5 6 7
while True: inp = input(":") inp = inp.rstrip("\n")
8 9 10 11 12
if inp == 'x': for name in queue: print(name) exit()
13 14 15 16
if inp == 's': print(len(queue)) continue
17 18 19 20 21 22 23
if inp == 'n': if len(queue) > 0: print("next is {}".format(queue.popleft())) else: print("the queue is empty") continue
24 25
queue.append(inp)
Solution: Reverse Polish calculator (stack) with lists 1
stack = []
2 3 4 5
print("x = eXit, s = Show, [+-*/=]") while True: val = input(':')
6 7 8 9
if val == 's': print(stack) continue
10 11 12
if val == 'x': break
13 14
if val == '+':
152
Lists 15 16 17 18
a = stack.pop() b = stack.pop() stack.append(a+b) continue
19 20 21 22 23 24
if val == '-': a = stack.pop() b = stack.pop() stack.append(a-b) continue
25 26 27 28 29 30
if val == '*': a = stack.pop() b = stack.pop() stack.append(a*b) continue
31 32 33 34 35 36
if val == '/': a = stack.pop() b = stack.pop() stack.append(a/b) continue
37 38 39 40
if val == '=': print(stack.pop()) continue
41 42
stack.append(float(val))
Solution: Reverse Polish calculator (stack) with deque 1
from collections import deque
2 3
stack = deque()
4 5 6
while True: val = input(':')
7 8 9
if val == 'x': break
10 11
if val == '+':
153
Lists 12 13 14 15
a = stack.pop() b = stack.pop() stack.append(a+b) continue
16 17 18 19 20 21
if val == '*': a = stack.pop() b = stack.pop() stack.append(a*b) continue
22 23 24 25 26
if val == '=': print(stack.pop()) continue
27 28
stack.append(float(val))
Solution: MasterMind 1
import random
2 3 4
width = 4 USED = '_'
5 6 7
hidden = random.sample(range(10), width) # print(hidden)
8 9 10
while True: # print(hidden)
11 12 13 14 15 16 17 18
inp = input("your guess ({} digits):".format(width)) if inp == 'x': print("Bye") exit() if len(inp) != width: print("We need exactly {} characters".format(width)) continue
19 20 21 22
guess = [] for cr in inp: guess.append(int(cr))
154
Lists 23 24
# guess = list(map(int, inp)) # print(guess)
25 26 27 28
if hidden == guess: print("Match!") break
29 30 31
my_hidden = hidden[:] my_guess = guess[:]
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
result = '' for i in range(width): if my_hidden[i] == my_guess[i]: result += '*' my_hidden[i] = USED my_guess[i] = USED for i in range(width): if my_guess[i] == USED: continue if my_guess[i] in my_hidden: loc = my_hidden.index(my_guess[i]) my_hidden[loc] = USED guess[i] = USED result += '+'
47 48
print(''.join(result))
MasterMind to debug Debug the following version of the MasterMind game. 1
import random
2 3 4 5
def number_generator(): y = [0, 0, 0, 0]
6 7 8 9 10 11
for i in range(0, 4): y[i] = random.randrange(0, 10) # print(y) if i: number += str(y[i])
155
Lists 12 13 14 15
else: number = str(y[i]) # print(number) return number
16 17 18 19 20 21 22 23 24
def user_input(): x = input("Type in 4 digits number:") if len(x) == 4: return x else: print("wrong input") user_input()
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
def string_compare(x, y): r = 0 q = 0 for i in range(0, 4): if x[i] == y[i]: r += 1 continue for j in range(0, 4): if x[i] == y[j]: if i == j: continue else: q += 1 break return r, q
42 43 44 45 46 47 48 49 50
def print_result(r): print("") for i in range(0, r[0]): print("*", end="") for i in range(0, r[1]): print("+", end="") print("\n")
51 52 53 54
def main(): comp = number_generator()
156
Lists 55 56 57 58 59 60 61 62 63
result = 0 while True: user = user_input() result = string_compare(comp, user) print_result(result) # print(result) if result[0] == 4: print("Correct!") return
64 65 66
main()
Debugging Queue The following implementation has a bug. (Even though the n was supposed to remove the element and the code seems to mean that it does, we still see two items after we removed the first.) The question is how to debug this? 1
q = []
2 3 4
while True: name=input("your name: ")
5 6 7
if name=="n": print(q.pop(0))
8 9 10 11
if name=="x": print(q) exit()
12 13 14 15 16 17 18
if name=="s": print(len(q)) exit() else: q.append(name) continue
157
Lists 1 2 3 4 5 6
your your your Foo your 2
name: Foo name: Bar name: n name: s
sort 1 2 3 4
planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn'] print(planets) # ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn'] planets.sort() print(planets) # ['Earth', 'Jupiter', 'Mars', 'Mercury', 'Saturn', 'Venus']
5 6 7
planets.sort(reverse=True) print(planets) # ['Venus', 'Saturn', 'Mercury', 'Mars', 'Jupiter', 'Earth']
sort numbers 1 2 3 4
numbers = [7, 2, -4, 19, 8] print(numbers) numbers.sort() print(numbers)
# [7, 2, -4, 19, 8] # [-4, 2, 7, 8, 19]
5 6 7
numbers.sort(reverse=True) print(numbers)
# [19, 9, 7, 2, -4]
8 9 10
numbers.sort(key=abs, reverse=True) print(numbers) # [19, 9, 7, -4, 2]
sort mixed 1 2 3 4
mixed = [100, 'foo', 42, 'bar'] print(mixed) mixed.sort() print(mixed)
Python 2 puts the numbers first in numerical order and then the strings in ASCII order.
Lists 1 2
[100, 'foo', 42, 'bar'] [42, 100, 'bar', 'foo']
In Python 3 it throws an exception. 1 2 3 4 5
[100, 'foo', 42, 'bar'] Traceback (most recent call last): File "examples/lists/sort_mixed.py", line 5, in mixed.sort() TypeError: unorderable types: str() < int()
key sort • Another example for using a key. • To sort the list according to length
1 2
animals = ['chicken', 'cow', 'snail', 'elephant'] print(animals)
3 4 5
animals.sort() print(animals)
6 7 8
animals.sort(key=len) print(animals)
9 10 11
1 2 3 4
animals.sort(key=len, reverse=True) print(animals)
['chicken', 'cow', 'snail', 'elephant'] ['chicken', 'cow', 'elephant', 'snail'] ['cow', 'snail', 'chicken', 'elephant'] ['elephant', 'chicken', 'snail', 'cow']
sort with sorted
158
159
Lists 1 2
animals = ['chicken', 'cow', 'snail', 'elephant'] print(animals) # ['chicken', 'cow', 'snail', 'elephant']
3 4 5 6
s = sorted(animals) print(s) print(animals)
# ['chicken', 'cow', 'elephant', 'snail'] # ['chicken', 'cow', 'snail', 'elephant']
7 8 9 10
r = sorted(animals, reverse=True, key=len) print(r) # ['elephant', 'chicken', 'snail', 'cow'] print(animals) # ['chicken', 'cow', 'snail', 'elephant']
sort vs. sorted The sort() method will sort a list in-place and return None. The built-in sorted() function will return the sorted list and leave the original list intact.
key sort with sorted To sort the list according to length using sorted 1 2
animals = ['snail', 'cow', 'elephant', 'chicken'] animals_in_abc = sorted(animals)
3 4 5
print(animals) print(animals_in_abc)
6 7 8
1 2 3
animals_by_length = sorted(animals, key=len) print(animals_by_length)
['snail', 'cow', 'elephant', 'chicken'] ['chicken', 'cow', 'elephant', 'snail'] ['cow', 'snail', 'chicken', 'elephant']
Sorting characters of a string
160
Lists 1 2 3 4 5
letters = 'axzb' print(letters) s = sorted(letters) print(s) print(letters)
# 'axzb' # ['a', 'b', 'x', 'z'] # 'axzb'
6 7 8
r = ''.join(sorted(letters)) print(r) # abxz
range 1 2 3 4 5 6
for i in range(11, 18, 2): print(i) # 11 # 13 # 15 # 17
7 8 9 10 11
for i in range(5, 7): print(i) # 5 # 6
12 13 14 15 16 17
for i in range(3): print(i) # 0 # 1 # 2
Looping over index 1 2 3
things = ['abc', 'def', 'ghi', 42] for var in things: print(var)
161
Lists 1 2 3
things = ['abc', 'def', 'ghi', 42] for i in range(len(things)): print(i, things[i])
4 5 6 7 8
# # # #
0 1 2 3
abc def ghi 42
Enumerate lists 1 2 3
planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn'] for idx, planet in enumerate(planets): print(idx, planet)
4 5 6 7 8
1 2 3 4 5 6
print('') enu = enumerate(planet) print(enu.__class__.__name__) print(enu)
0 1 2 3 4 5
Mercury Venus Earth Mars Jupiter Saturn
7 8 9
enumerate
List operators
162
Lists 1 2
a = ['one', 'two'] b = ['three']
3 4
print(a)
# ['one', 'two']
5 6 7
print(a * 2) # ['one', 'two', 'one', 'two'] print(2 * a) # ['one', 'two', 'one', 'two']
8 9 10
print(a + b) # ['one', 'two', 'three'] print(b + a) # ['three', 'one', 'two']
List of lists 1 2
x = ['abc', 'def'] print(x) # ['abc', 'def']
3 4 5 6
y = [x, 'xyz'] print(y) print(y[0])
# [['abc', 'def'], 'xyz'] # ['abc', 'def']
print(x[0]) print(y[0][0])
# #
7 8 9
abc abc
List assignment List assignment works in “parallel” in Python.
1 2 3
x, y = 1, 2 print(x) print(y)
# 1 # 2
x, y = y, x print(x) print(y)
# 2 # 1
4 5 6 7
163
Lists 1
x,y = f()
# works if f returns a list of 2 elements
It will throw a run-time ValueError exception if the number of values in the returned list is not 2. (Both for fewer and for more return values).
List documentation • datastructures⁸¹
tuple Tuple • A tuple is a fixed-length immutable list. It cannot change its size or content. • A tuple is denoted with parentheses: (1,2,3) 1 2
t = ('a', 'b', 'c') print(t) # ('a', 'b', 'c')
List • Elements of a list can be changed via their index or via the list slice notation. • A list can grow and shrink using append and pop methods or using the slice notation. • A list is denoted with square brackets: [1, 2, 3] 1 2 3 4
l = ['abc', 'def', 'qqrq'] t = tuple(l) print(l) # ['abc', 'def', 'qqrq'] print(t) # ('abc', 'def', 'qqrq')
Tuples are rarely used. There are certain places where Python or some module require tuple (instead of list) or return a tuple (instead of a list) and in each place it will be explained. Otherwise you don’t need to use tuples. e.g. keys of dictionaries can be tuple (but not lists).
Sort tuples Sorting tuples or list, or other complex structures ⁸¹http://docs.python.org/tutorial/datastructures.html
164
Lists 1 2 3 4 5 6 7
students = [ ('John', 'A', 2), ('Zoro', 'C', 1), ('Dave', 'B', 3), ] print(students) # [('John', 'A', 2), ('Zoro', 'C', 1), ('Dave', 'B', 3)]
8 9 10 11
print(sorted(students)) # [('Dave', 'B', 3), ('John', 'A', 2), ('Zoro', 'C', 1)] # sort by the first element of each tuple
12 13 14 15
print(sorted(students, key=lambda s : s[1])) # [('John', 'A', 2), ('Dave', 'B', 3), ('Zoro', 'C', 1)] # sort by the 2nd element of the tuples (index 1)
16 17 18 19
print(sorted(students, key=lambda s : s[2])) # [('Zoro', 'C', 1), ('John', 'A', 2), ('Dave', 'B', 3)] # sort by the 3rd element of the tuples (index 2)
20 21 22 23 24 25 26
from operator import itemgetter print(sorted(students, key=itemgetter(2))) # [('Zoro', 'C', 1), ('John', 'A', 2), ('Dave', 'B', 3)] # maybe this is more simple than the lambda version # and probably faster
Exercise: color selector menu • In a script have a list of colors. Write a script that will display a menu (a list of numbers and the corresponding color) and prompts the user for a number. The user needs to type in one of the numbers. That’s the selected color. 1. 2. 3. 4.
blue green yellow white
• For extra credit make sure the system is user-proof and it won’t blow up on various incorrect input values. (e.g Floating point number. Number that is out of range, non-number) • For more credit allow the user to supply the number of the color on the command line. python color.py 3. If that is available, don’t prompt.
Lists
165
• For further credit allow the user to provide the name of the color on the command line: python color.py yellow Can you handle color names that are not in the expected case (e.g. YelloW)? • Any more ideas for improvement?
Exercise: count digits Given a list of numbers numbers = [1203, 1256, 312456, 98], count how many times each digit appears? The output will look like this: 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9
1 3 3 2 1 2 2 0 1 1
Exercise: Create list Given a list of strings with words separated by spaces, create a single list of all the words. 1 2 3 4 5
lines = [ 'grape banana mango', 'nut orange peach', 'apple nut banana apple mango', ]
6 7 8
fruits = ['grape', 'banana', 'mango', 'nut', 'orange', 'peach', 'apple', 'nut', 'ban\ ana', 'apple', 'mango']
Then create a list of unique values sorted in alphabetical order. 1
unique_fruites = ['apple', 'banana', 'grape', 'mango', 'nut', 'orange', 'peach']
Exercise: Count words
166
Lists 1 2 3
celestial_objects = [ 'Moon', 'Gas', 'Asteroid', 'Dwarf', 'Asteroid', 'Moon', 'Asteroid' ]
Expected output: 1 2 3 4
Moon Gas Asteroid Dwarf
2 1 3 1
Exercise: Check if number is prime Write a program that gets a number on the commnad line a prints “True” if the number is a prime number or “False” if it isn’t. 1 2 3 4
python is_prime.py 42 False python is_prime.py 19 True
Exercise: DNA sequencing • A, C, T, G are called bases or nucleotides • Given a sequence like ‘ACCGXXCXXGTTACTGGGCXTTGTXX’ (nucleotides mixed up with other elements) • First return the sequences containing only ACTG. The above string can will be changed to [‘ACCG’, ‘C’, ‘GTTACTGGGC’, ‘TTGT’]. • Then sort them by lenght. Expected result: [‘GTTACTGGGC’, ‘ACCG’, ‘TTGT’, ‘C’] • What if the original string contains more than on type of foreing elements? e.g. ‘ACCGXXCXXYYGTTQRACQQTGGGCXTTGTXX’. Can you do the same?
Solution: menu
Lists 1 2 3
167
colors = ['blue', 'yellow', 'black', 'purple'] for ix in range(len(colors)): print("{}) {}".format(ix+1, colors[ix]))
4 5 6 7
selection = input("Select color: ") if not selection.isdecimal(): exit(f"We need a number between 1 and {len(colors)}")
8 9 10
if int(selection) < 1 or int(selection) > len(colors): exit(f"The number must be between 1 and {len(colors)}")
11 12 13
col = int(selection) - 1 print(colors[col])
• We would like to show a menu where each number corresponds to one element of the list so this is one of the places where we need to iterate over the indexes of a list. • len(colors) gives us the length of the list (in our case 4) • range(len(colors)) is the range of numbers betwwen 0 and 4 (in our case), menaing 0, 1, 2, 3. • (Sometimes people explicetly write 4 in this solution, but if later we change the list and include another color we’ll have to remember updating this number as well. This is error prone and it is very easy to deduct this number from the data we already have. (The list.)) • We start the list from 0, but when we display the menu we would like to show the numbers 1-4 to make it more human friendly. Therefore we show ix+1 and the color from locations ix. • We ask for input and save it in a variable. • We use the isdecimal method to check if the user typed in a decimal number. We give an error and exit if not. • Then we check if the users provided a number in the correct range of values. We give an error and exit if not. • then we convert the value to the correct range of numbers (remember, the user sees and selects numbers between 1-4 and we need them between 0-3).
Solution: count digits
Lists 1
168
numbers = [1203, 1256, 312456, 98]
2 3
count = [0] * 10 # same as [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
4 5 6 7
for num in numbers: for char in str(num): count[int(char)] += 1
8 9 10
for d in range(0, 10): print("{} {}".format(d, count[d]))
First we have to decide where are we going to store the counts. A 10 element long list seems to fit our requirements so if we have 3 0s and 2 8s we would have [3, 0, 0, 0, 0, 0, 0, 0, 2, 0]. • We have a list of numbers. • We need a place to store the counters. For this we create a variable called counter which is a list of 10 0s. We are going to count the number of times the digit 3 appears in counters[3]. • We iterate over the numbers so num is the current number. (e.g. 1203) • We would like to iterate over the digits in the curreent number now, but if we write for var in num we will get an error TypeError: 'int' object is not iterable because num is a number, but numbers are not iterables, so we we cannot iterate over them. So we need to convert it to a string useing str. • On each iteration char will be one character (which in or case we assume that will be a digit, but still stored as a string). • int(char) will convert the string to a number so for example “2” will be converted to 2. • count[int(char)] is going to be char[2] if char is “2”. That’s the location in the list where we count how many times the digit 2 appears in our numbers. • We increment it by one as we have just encountered a new copy of the given digit. • That finished the data collection. • The second for-loop iterates over all the “possible digits” that is from 0-9, prints out the digit and the counter in the respective place.
Solution: Create list
Lists 1 2 3 4 5
lines = [ 'grape banana mango', 'nut orange peach', 'apple nut banana apple mango', ]
6 7 8 9 10
one_line = ' '.join(lines) print(one_line) fruits = one_line.split() print(fruits)
11 12 13 14 15 16
unique_fruits = [] for word in fruits: if word not in unique_fruits: unique_fruits.append(word) print(sorted(unique_fruits))
17 18 19 20 21
# a simpler way using a set, but we have not learned sets yet. unique = sorted(set(fruits)) print(unique)
Solution: Count words 1 2 3
celestial_objects = [ 'Moon', 'Gas', 'Asteroid', 'Dwarf', 'Asteroid', 'Moon', 'Asteroid' ]
4 5 6
names = [] counter = []
7 8 9 10 11 12 13 14
for name in celestial_objects: if name in names: idx = names.index(name) counter[idx] += 1 else: names.append(name) counter.append(1)
15 16 17
for i in range(len(names)): print("{:12} {}".format(names[i], counter[i]))
169
Lists
Solution: Check if number is prime 1
import sys
2 3
n = int(sys.argv[1])
4 5
#print(n)
6 7 8 9 10 11
is_prime = True for i in range(2, int( n ** 0.5) + 1): if n % i == 0: is_prime = False break
12 13
print(is_prime)
14 15 16
# math.sqrt(n) might be clearer than n ** 0.5
Solution: DNA sequencing 1 2 3
dna = 'ACCGXXCXXGTTACTGGGCXTTGT' sequences = dna.split('X') sequences.sort(key=len, reverse=True)
4 5 6 7 8
new_seq = [] for w in sequences: if len(w) > 0: new_seq.append(w)
9 10 11
print(sequences) print(new_seq)
Solution: DNA sequencing with filter
170
171
Lists 1 2 3
dna = 'ACCGXXCXXGTTACTGGGCXTTGT' sequences = dna.split('X') sequences.sort(key=len, reverse=True)
4 5 6
def not_empty(x): return len(x) > 0
7 8 9 10
print(sequences) sequences = list( filter(not_empty, sequences) ) print(sequences)
Solution: DNA sequencing with filter and lambda 1 2 3
dna = 'ACCGXXCXXGTTACTGGGCXTTGT' sequences = dna.split('X') sequences.sort(key=len, reverse=True)
4 5 6 7
print(sequences) sequences = list( filter(lambda x: len(x) > 0, sequences) ) print(sequences)
. extend][].extend 1
names = ['Foo Bar', 'Orgo Morgo']
2 3 4
names.extend(['Joe Doe', 'Jane Doe']) print(names) # ['Foo Bar', 'Orgo Morgo', 'Joe Doe', 'Jane Doe']
append vs. extend What is the difference between [].append and [].extend ? The method append adds its parameter as a single element to the list, while extend gets a list and adds its content.
172
Lists 1 2 3 4
names = ['Foo Bar', 'Orgo Morgo'] more = ['Joe Doe', 'Jane Doe'] names.extend(more) print(names) # ['Foo Bar', 'Orgo Morgo', 'Joe Doe', 'Jane Doe']
5 6 7 8
names = ['Foo Bar', 'Orgo Morgo'] names.append(more) print(names) # ['Foo Bar', 'Orgo Morgo', ['Joe Doe', 'Jane Doe']]
9 10 11 12
names = ['Foo', 'Bar'] names.append('Qux') print(names) # ['Foo', 'Bar', 'Qux']
13 14 15 16
names = ['Foo', 'Bar'] names.extend('Qux') print(names) # ['Foo', 'Bar', 'Q', 'u', 'x']
split and extend When collecting data which is received from a string via splitting, we would like to add the new elements to the existing list:
1 2 3 4
lines = [ 'abc def ghi', 'hello world', ]
5 6
collector = []
7 8 9 10
for l in lines: collector.extend(l.split()) print(collector)
11 12 13
# ['abc', 'def', 'ghi'] # ['abc', 'def', 'ghi', 'hello', 'world']
Files File types: Text vs Binary You probably know many file types such as Images (png, jpg, …), Word, Excel, mp3, mp4, csv, and now also .py files. Internally there are two big categories. Text and Binary files. Text files are the ones that look readable if you open them with a plain text editor such as Notepad. Binary files will look like a mess if you opened them in Noetpad. For Binary files you need a special application to “look” at their content. For example the Excel and Word programs for the appropriate files. Some image viewer application to view all the images. VLC to look at an mp4. Some application to hear the content of mp3 files.
• Text: .txt, csv, .py, .pl, …, HTML , XML, YAML, JSON • Binary: Images, Zip files, Word, Excel, .exe, mp3, mp4
In Python you have specialized modules for each well-knonw binary type to handle the files of that format. Text files on the other hand can be handled by low level file-reading functions, however even for those we usually have modules that know how to read and interpret the specific formats. (e.g. CSV, HTML, XML, YAML, JSON parsers)
Open vs. Read vs. Load The expression “open a file” has two distinct meanings for programmers and users of software. For a user of Word, for example, “open the file” would mean to be able to see its content in a formatted way inside the editor. When a programmer - now acting as a regular user - opens a Python file in an editor such as Notepad++ or Pycharm, the expectation is to see the content of that program with nice colors.
174
Files
However in order to provide this the programmer behind these applications had to do several things.
• Connect to a file on the disk (aka. “opening the file” in programmer speak). • Read the content of the file from the disk to memory. • Format the content read from the file as expected by the user of that application.
Binary files: Images This is just a quick example how to use the Pillow module to handle images. There is a whole chapter on dealing with images.
• Pillow⁸² 1 2
from PIL import Image import sys
3 4 5
if len(sys.argv) !=2: exit(f"Usage: {sys.argv[0]} FILENAME")
6 7
in_file = sys.argv[1]
8 9 10 11 12
img = Image.open(in_file) print(img.size) # a tuple print(img.size[0]) # width print(img.size[1]) # height
Reading an Excel file There are many ways to deal with Excel files as well.
• openpyxl⁸³ ⁸²https://pillow.readthedocs.io/en/stable/ ⁸³https://openpyxl.readthedocs.io/en/stable/
175
Files 1 2
import openpyxl import sys
3 4 5
if len(sys.argv) !=2: exit(f"Usage: {sys.argv[0]} FILENAME")
6 7
in_file = sys.argv[1]
8 9 10 11
wb = openpyxl.load_workbook(filename = in_file) for ws in wb.worksheets: print(ws.title)
12 13 14
ws = wb.worksheets[0] print(ws['A1'].value)
Open and read file (easy but not recommended) In some code you will encounter the following way of opening files. This was used before “with” was added to the language. It is not a recommended way of opening a file as you might easily forget to call “close” and that might cause trouble. For example you might loose data. Don’t do that. I am showing this as the first example, because it is easuer to understand.
1
filename = 'examples/files/numbers.txt'
2 3 4 5 6
fh = open(filename, 'r') for line in fh: print(line) fh.close()
# duplicate newlines
Open and read file using with (recommended)
176
Files 1
filename = 'examples/files/numbers.txt'
2 3 4 5
with open(filename, 'r') as fh: for line in fh: print(line)
# open(filename) would be enough # duplicate newlines
6 7
# close is called when we leave the 'with' context
Read file remove newlines 1
filename = 'examples/files/numbers.txt'
2 3 4 5 6
with open(filename, 'r') as fh: for line in fh: line = line.rstrip("\n") print(line)
Filename on the command line 1
import sys
2 3 4 5 6 7 8
def main(): if len(sys.argv) != 2: exit("Usage: " + sys.argv[0] + " FILENAME") filename = sys.argv[1] with open(filename) as fh: print("Working on the file", filename)
9 10
1 2
main()
$ python single.py Usage: single.py FILENAME
3 4 5
$ python single.py numbers.txt Working on the file numbers.txt
Filehandle with return
177
Files 1
import sys
2 3 4
def process_file(filename): with open(filename, 'r') as fh:
5 6 7 8 9
for line in fh: line = line.rstrip("\n") if len(line) > 0 and line[0] == '#': return
10 11 12
if len(line) > 1 and line[0:2] == '//': return
13 14 15
# process the line print(line)
16 17 18
process_file(sys.argv[0])
Read all the lines into a list There are rare cases when you need the whole content of a file in the memory and you cannot process it line by line. In those rare cases we have several options. readlines will read the whole content into a list converting each line from the file to be an element in the list. Beware though, if the file is too big, it might not fit in the free memory of the computer.
1
filename = 'examples/files/numbers.txt'
2 3 4
with open(filename, 'r') as fh: lines_list = fh.readlines()
5 6 7
# print number of lines print(len(lines_list))
8 9 10
for line in lines_list: print(line, end="")
# reads all the lines into a list
178
Files
Read all the characters into a string (slurp) In some other cases, especially if you are looknig for some pattern that starts on one line but ends on another line. you’d be better off having the whole file as a single string in a variable. This is where the read method comes in handy. It can also be used to read in chunks of the file.
1
filename = 'examples/files/numbers.txt'
2 3 4
with open(filename, 'r') as fh: lines_str = fh.read() # reads all the lines into a string
5 6
print(len(lines_str))
# number of characters in file
print(lines_str)
# the content of the file
7 8
read(20) will read 20 bytes.
Not existing file 1
filename = 'examples/files/unicorns.txt'
2 3 4 5
with open(filename, 'r') as fh: lines = fh.read() print("still running")
6 7 8 9 10
# Traceback (most recent call last): # File "examples/files/open_file.py", line 5, in # with open(filename, 'r') as fh: # IOError: [Errno 2] No such file or directory: 'examples/files/unicorns.txt'
Open file exception handling Exception handling
Files 1
filename = 'examples/files/unicorns.txt'
2 3 4 5 6 7 8 9
try: with open(filename, 'r') as fh: lines = fh.read() except Exception as err: print('There was some error in the file operations.') print(err) print(type(err).__name__)
10 11
print('Still running.')
Open many files - exception handling 1
import sys
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
def main(): for filename in sys.argv[1:]: try: #do_some_stuff(filename) with open(filename) as fh: total = 0 count = 0 for line in fh: number = float(line) total += number count += 1 print("Average: ", total/count) except Exception as err: print(f"trouble with '{filename}': Error: {err}")
18 19
1 2 3 4
main()
23 1 192 17
179
Files
180
1
1
$ python average_from_files.pyt number_per_line.txt empty.txt number_per_line2.txt
2
5
Average: 58.25 trouble with empty.txt Average: 3.5
1
$ python average_from_files.py numbers.txt
3 4
2 4
trouble with 'numbers.txt': Error: could not convert string to float: '23 345 12345\\ n'
1
$ python average_from_files.py more_numbers.txt
3
2 3 4
trouble with 'more_numbers.txt': Error: [Errno 2] No such file or directory: 'more_n\ umbers.txt'
Writing to file 1
filename = 'data.txt'
2 3 4
with open(filename, 'w') as out: out.write('text\n')
Append to file 1
filename = 'data.txt'
2 3 4
with open(filename, 'a') as out: out.write('append more text\n')
Binary mode
Files 1 2 3
import sys if len(sys.argv) != 2: exit("Need name of file")
4 5
filename = sys.argv[1]
6 7 8 9 10 11 12 13 14 15 16
1
try: with open(filename, 'rb') as fh: while True: binary_str = fh.read(1000) print(len(binary_str)) if len(binary_str) == 0: break # do something with the content of the binary_str except Exception: pass
python examples/files/read_binary.py examples/pil/first.png
2 3 4 5 6 7 8 9
1000 1000 1000 1000 1000 775 0
Does file exist? Is it a file? • os.path.exists⁸⁴ • os.path.isfile⁸⁵ • os.path.isdir⁸⁶
Direct access of a line in a file
⁸⁴https://docs.python.org/library/os.path.html#os.path.exists ⁸⁵https://docs.python.org/library/os.path.html#os.path.isfile ⁸⁶https://docs.python.org/library/os.path.html#os.path.isdir
181
182
Files 1 2 3 4
1 2 3 4
1 2 3
names = ['Foo', 'Bar', 'Baz'] for name in names: print(name) print(names[1])
Foo Bar Baz Bar
import sys if len(sys.argv) != 2: exit(f"Run {sys.argv[0]} FILENAME")
4 5
filename = sys.argv[1]
6 7 8 9 10
# We can iterate over the lines #with open(filename, 'r') as fh: # for line in fh: # print(line)
11 12 13 14
1 2 3 4
# We cannot access an element with open(filename, 'r') as fh: print(fh[2])
Traceback (most recent call last): File "examples/files/fh_access.py", line 14, in print(fh[2]) TypeError: '_io.TextIOWrapper' object is not subscriptable
This does NOT work because files can only be accessed sequentially.
Files 1 2 3
183
import sys if len(sys.argv) != 2: exit(f"Run {sys.argv[0]} FILENAME")
4 5
filename = sys.argv[1]
6 7 8 9
1 2 3
with open(filename, 'r') as fh: rows = fh.readlines() print(rows[2])
import sys if len(sys.argv) != 2: exit(f"Run {sys.argv[0]} FILENAME")
4 5
filename = sys.argv[1]
6 7 8 9 10 11 12 13
with open(filename, 'r') as fh: count = 0 for row in fh: if count == 2: break count += 1 print(row)
Exercise: count numbers 1 2
23 345 12345 67 189 23 17
1. Given the file examples/files/numbers.txt (or a similar file), count how many times each digit appears? The output will look like this. Just different values. 2. Save the results in a file called report.txt.
Files 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9
0 3 3 4 2 2 1 2 1 1
Exercise: strip newlines How to read all the lines of a file into a list and remove trailing newlines?
Exercise: print lines with Report: Given a file that looks like this: 1 2 3
This is a text report there are some lines that start with Report: 23 Other linese has this somewhere in the middle.
4 5
Begin report
6 7
Report: -3
8 9 10 11
Like this. Report: 17 More lines starting with Report: 44
12 13
End report
14 15 16
We will have some exercise with this file. Maybe 4 exercises. Report: 123
• Print out the first line that starts with Report: • Print out all the lines that have Report: in it • Print out all the lines that start with Report:
184
Files
185
• Print out the numbers that are after Report: • Add the numbers that after after Report: • Now do the same, but only take account lines between the Begin and End secition.
Exercise: color selector Create a file similar to the colors.txt file and use it as the list of colors in the earlier example where we prompted for a color. 1 2 3 4
blue yellow white green
Extend the previous example by letting the user provide the name of the file on the command line: python color.py examples/files/color.txt
Exercise: ROT13 Implement ROT13⁸⁷: • Create a function that given a string return the rot13 of it. • Create a script that given a file it will replace it with the rot13 of it. How to check if it works properly: 1 2 3 4 5 6 7
txt = "any text" encrypted = rot13(txt) decrypted = rot13(encrypted) if decrypted == text: print("Good") else: print("Bad")
Exercise: Combine lists ⁸⁷https://en.wikipedia.org/wiki/ROT13
186
Files 1 2 3
1 2 3
Tomato=78 Avocado=23 Pumpkin=100
Cucumber=17 Avocado=10 Cucumber=10
Write a script that takes the two files and combines them adding the values for each vegetable. The expected result is: 1 2 3 4
Avocado=33 Cucumber=27 Pumpkin=100 Tomato=78
Solution: count numbers 1
import sys
2 3 4
if len(sys.argv) < 2: exit("Need name of file.")
5 6 7 8 9 10 11 12
counter = [0] * 10 filename = sys.argv[1] with open(filename) as fh: for line in fh: for c in line.rstrip("\n"): if c == ' ': continue
13 14 15
c = int(c) counter[c] += 1
16 17 18
for i in range(10): print("{} {}".format(i, counter[i]))
Solution: strip newlines
Files 1 2 3 4 5 6 7
import sys filename = sys.argv[0] with open(filename) as fh: lines = [] for line in fh: lines.append(line.rstrip("\n")) print(lines)
Solution: print lines with Report: 1
import sys
2 3 4 5
if len(sys.argv) !=2: exit(f"Usage: {sys.argv[0]} FILENAME") # text_report.txt
6 7
in_file = sys.argv[1]
8 9 10 11 12 13
with open(in_file) as fh: for row in fh: row = row.rstrip("\n") if 'Report:' in row: print(row)
14 15
print('-' * 20)
16 17 18 19 20 21
with open(in_file) as fh: for row in fh: row = row.rstrip("\n") if row.startswith('Report:'): print(row)
22 23
print('-' * 20)
24 25 26 27 28 29 30 31 32
total = 0 with open(in_file) as fh: for row in fh: row = row.rstrip("\n") #if row.startswith('Report:'): if 'Report:' in row: parts = row.split(':') print(int(parts[1]))
187
188
Files 33 34
total += int(parts[1]) print(f"Total: {total}")
Solution: color selector 1 2 3 4 5 6 7 8 9
def main(): try: with open('colors.txt') as fh: colors = [] for line in fh: colors.append(line.rstrip("\n")) except IOError: print("Could not open colors.txt") exit()
10 11 12
for i in range(len(colors)): print("{}) {}".format(i, colors[i]))
13 14 15
c = int(input("Select color: ")) print(colors[c])
16 17
main()
Solution: Combine lists 1 2 3 4 5 6 7
a_names = [] a_values = [] with open('examples/files/a.txt') as fh: for line in fh: k, v = line.rstrip("\n").split("=") a_names.append(k) a_values.append(int(v))
8 9 10 11 12 13 14 15 16
b_names = [] b_values = [] with open('examples/files/b.txt') as fh: for line in fh: k, v = line.rstrip("\n").split("=") b_names.append(k) b_values.append(int(v))
Files 17 18
c_names = [] c_values = []
19 20 21 22 23 24 25 26
for i in range(len(a_names)): if a_names[i] in c_names: j = c_names.index(a_names[i]) c_values[j] += a_values[i] else: c_names.append( a_names[i] ) c_values.append( a_values[i] )
27 28 29 30 31 32 33 34
for i in range(len(b_names)): if b_names[i] in c_names: j = c_names.index(b_names[i]) c_values[j] += b_values[i] else: c_names.append( b_names[i] ) c_values.append( b_values[i] )
35 36 37 38 39
with open('out.txt', 'w') as fh: for i in range(len(c_names)): fh.write("{}={}\n".format(c_names[i], c_values[i]))
Filehandle using with and not using it 1
filename = 'examples/files/numbers.txt'
2 3 4 5 6 7 8
fh = open(filename, 'r') print(fh) # data = fh.read() # do something with the data fh.close() print(fh) #
9 10 11 12 13 14 15
with open(filename, 'r') as fh: print(fh) # data = fh.read() print(fh) #
189
Dictionary (hash) What is a dictionary • Unordered key-value pairs. • Keys are immutables (numbers, strings, tuples). • Values can be any object.
When to use dictionaries • • • •
ID to Name mapping. Object to Count mapping. Name of a feature to value of the feature. Name of an attribute to value of the attribute.
Dictionary 1 2 3
user = {} user['name'] = 'Foobar' print(user) # {'name': 'Foobar'}
4 5 6
user['email'] = '[email protected]' print(user) # {'name': 'Foobar', 'email': '[email protected]'}
7 8 9
the_name = user['name'] print(the_name) # Foobar
10 11 12 13
field = 'name' the_value = user[field] print(the_value) # Foobar
14 15 16
user['name'] = 'Edith Piaf' print(user) # {'name': 'Edith Piaf', 'email': '[email protected]'}
keys
191
Dictionary (hash) 1 2 3 4
user = { 'fname': 'Foo', 'lname': 'Bar', }
5 6
print(user)
# {'lname': 'Bar', 'fname': 'Foo'}
7 8
print(user.keys())
# ['lname', 'fname']
• Keys are returned in seemingly random order.
Loop over keys 1 2 3 4
user = { 'fname': 'Foo', 'lname': 'Bar', }
5 6 7
for k in user.keys(): print(k)
8 9 10
# lname # fname
11 12 13
for k in user.keys(): print("{} -> {}".format(k, user[k]))
14 15 16
# lname -> Bar # fname -> Foo
Loop over dictionary keys Looping over the “dictionary” is just like looping over the keys, but personally I prefer when we use the somedictionary.keys() expression.
Dictionary (hash) 1 2 3 4
user = { 'fname': 'Foo', 'lname': 'Bar', }
5 6 7
for k in user: print("{} -> {}".format(k, user[k]))
8 9 10
# lname -> Bar # fname -> Foo
Loop using items 1 2 3 4 5
people = { "foo" : "123", "bar" : "456", "qux" : "789", }
6 7 8
1 2 3
1 2 3 4
for name, uid in people.items(): print("{} => {}".format(name, uid)) foo => 123 bar => 456 qux => 789 user = { 'fname': 'Foo', 'lname': 'Bar', }
5 6 7 8
for t in user.items(): # returns tuples print("{} -> {}".format(t[0], t[1])) #print("{} -> {}".format(*t))
9 10 11
# lname -> Bar # fname -> Foo
values • Values are returned in the same random order as the keys are.
192
193
Dictionary (hash) 1 2 3 4
user = { 'fname': 'Foo', 'lname': 'Bar', }
5 6
print(user)
# {'lname': 'Bar', 'fname': 'Foo'}
7 8
print(user.keys())
# ['lname', 'fname']
print(user.values())
# ['Bar', 'Foo']
9 10
Not existing key If we try to fetch the value of a key that does not exist, we get an exception. 1 2 3 4 5
def main(): user = { 'fname': 'Foo', 'lname': 'Bar', }
6 7 8
print(user['fname']) print(user['email'])
9 10
1 2 3 4 5 6 7
main()
Foo Traceback (most recent call last): File "examples/dictionary/no_such_key.py", line 11, in main() File "examples/dictionary/no_such_key.py", line 9, in main print(user['email']) KeyError: 'email'
Get key If we use the get method, we get None if the key does not exist.
194
Dictionary (hash) 1 2 3 4 5
user = { 'fname': 'Foo', 'lname': 'Bar', 'address': None, }
6 7 8 9
print(user.get('fname')) print(user.get('address')) print(user.get('email'))
10 11 12
1 2 3 4
print(user.get('answer', 42)) print(user.get('address', 23))
Foo None None 42 None will be interpreted as False, if checked as a boolean.
Does the key exist? 1 2 3 4
user = { 'fname': 'Foo', 'lname': 'Bar', }
5 6 7 8
print('fname' in user) print('email' in user) print('Foo' in user)
# True # False # False
9 10 11 12
for k in ['fname', 'email', 'lname']: if k in user: print("{} => {}".format(k, user[k]))
13 14 15
# fname => Foo # lname => Bar
195
Dictionary (hash) 1 2 3 4 5
True False False fname => Foo lname => Bar
Does the value exist? 1 2 3 4
user = { 'fname': 'Foo', 'lname': 'Bar', }
5 6 7
1 2
print('fname' in user.values()) print('Foo' in user.values())
# False # True
False True
Delete key 1 2 3 4 5
user = { 'fname': 'Foo', 'lname': 'Bar', 'email': '[email protected]', }
6 7
print(user) # {'lname': 'Bar', 'email': '[email protected]', 'fname': 'Foo'}
8 9 10 11 12
fname = user['fname'] del user['fname'] print(fname) # Foo print(user) # {'lname': 'Bar', 'email': '[email protected]'}
13 14 15 16
lname_was = user.pop('lname') print(lname_was) # Bar print(user) # {'email': '[email protected]'}
Dictionary (hash) 1 2 3 4 5
196
{'fname': 'Foo', 'lname': 'Bar', 'email': '[email protected]'} Foo {'lname': 'Bar', 'email': '[email protected]'} Bar {'email': '[email protected]'}
List of dictionaries 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
people = [ { 'name' : 'Foo Bar', 'email' : '[email protected]' }, { 'name' : 'Qux Bar', 'email' : '[email protected]', 'address' : 'Borg, Country', 'children' : [ 'Alpha', 'Beta' ] } ]
16 17 18 19
print(people) print(people[0]['name']) print(people[1]['children'][0])
20 21
1 2 3 4 5
print(list(map(lambda p: p['name'], people)))
[{'name': 'Foo Bar', 'email': '[email protected]'}, {'name': 'Qux Bar', 'email': 'qux@\ example.com', 'address': 'Borg, Country', 'children': ['Alpha', 'Beta']}] Foo Bar Alpha ['Foo Bar', 'Qux Bar']
Shared dictionary
197
Dictionary (hash) 1 2 3 4 5 6 7 8 9 10 11 12 13 14
people = [ { "name" "id" }, { "name" "id" }, { "name" "id" }, ]
: "Foo", : "1",
: "Bar", : "2",
: "Moo", : "3",
15 16 17 18 19 20 21 22
by_name = {} by_id = {} for p in people: by_name[ p['name' ] ] = p by_id[ p['id' ] ] = p print(by_name) print(by_id)
23 24 25 26
print(by_name["Foo"]) by_name["Foo"]['email'] = '[email protected]' print(by_name["Foo"])
27 28
1 2 3 4 5 6 7
print(by_id["1"])
{'Foo': {'name': 'Foo', 'id': '1'}, 'Bar': {'name': 'Bar', 'id': '2'}, 'Moo': {'name\ ': 'Moo', 'id': '3'}} {'1': {'name': 'Foo', 'id': '1'}, '2': {'name': 'Bar', 'id': '2'}, '3': {'name': 'Mo\ o', 'id': '3'}} {'name': 'Foo', 'id': '1'} {'name': 'Foo', 'id': '1', 'email': '[email protected]'} {'name': 'Foo', 'id': '1', 'email': '[email protected]'}
immutable collection: tuple as dictionary key
Dictionary (hash) 1 2
points = {} p1 = (2, 3)
3 4 5
points[p1] = 'Joe' points[(17, 5)] = 'Jane'
6 7 8 9 10 11
1 2 3 4 5 6 7
print(points) for k in points.keys(): print(k) print(k.__class__.__name__) print(points[k])
{(2, 3): 'Joe', (17, 5): 'Jane'} (2, 3) tuple Joe (17, 5) tuple Jane
immutable numbers: numbers as dictionary key 1 2 3 4 5 6
number = 23 17 3.14 42 }
{ : : : :
"Twenty three", "Seventeen", "Three dot fourteen", "The answer",
7 8 9 10
1 2 3
print(number) print(number[42]) print(number[3.14])
{23: 'Twenty three', 17: 'Seventeen', 3.14: 'Three dot fourteen', 42: 'The answer'} The answer Three dot fourteen
Sort dictionary by value
198
Dictionary (hash) 1 2 3 4 5
scores = 'Foo' 'Bar' 'Miu' }
{ : 10, : 34, : 88,
6 7
print(scores) # {'Miu': 88, 'Foo': 10, 'Bar': 34}
8 9 10 11 12
sorted_names = sorted(scores) # "sort dictionary" sorts the keys print(sorted_names) # ['Bar', 'Foo', 'Miu'] for s in sorted_names: print("{} {}".format(s, scores[s]))
13 14 15
# sort the values, but we cannot get the keys back! print(sorted(scores.values())) # [10, 34, 88]
16 17
print('')
18 19 20 21 22
# sort using a lambda expression sorted_names = sorted(scores, key=lambda x: scores[x]) for k in sorted_names: print("{} : {}".format(k, scores[k]))
23 24 25 26
# Foo : 10 # Bar : 34 # Miu : 88
27 28
print('')
29 30 31 32 33
# sort the keys according to the values: sorted_names = sorted(scores, key=scores.__getitem__) for k in sorted_names: print("{} : {}".format(k, scores[k]))
34 35 36 37
# Foo : 10 # Bar : 34 # Miu : 88
Sort dictionary keys by value
199
200
Dictionary (hash) 1 2 3 4 5 6
scores = { "Jane" "Joe" "George" "Hellena" }
: : : :
30, 20, 30, 90,
7 8 9
for name in scores.keys(): print(f"{name:8} {scores[name]}")
10 11 12 13
print('') for name in sorted(scores.keys()): print(f"{name:8} {scores[name]}")
14 15 16 17
print('') for val in sorted(scores.values()): print(f"{val:8}")
18 19 20 21
1 2 3 4
print('') for name in sorted(scores.keys(), key=lambda x: scores[x]): print(f"{name:8} {scores[name]}")
Jane Joe George Hellena
30 20 30 90
George Hellena Jane Joe
30 90 30 20
5 6 7 8 9 10 11 12 13 14
20 30 30 90
15 16 17 18 19
Joe Jane George Hellena
20 30 30 90
Dictionary (hash)
Insertion Order is kept Since Python 3.7
6
d = {} d['a'] = d['b'] = d['c'] = d['d'] = print(d)
1
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
1 2 3 4 5
1 2 3 4
Change order of keys in dictionary - OrderedDict 1
from collections import OrderedDict
2 3 4 5 6 7
d = OrderedDict() d['a'] = 1 d['b'] = 2 d['c'] = 3 d['d'] = 4
8 9 10
print(d) d.move_to_end('a')
11 12 13
print(d) d.move_to_end('d', last=False)
14 15
print(d)
16 17 18
for key in d.keys(): print(key)
201
Dictionary (hash) 1 2 3 4 5 6 7
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)]) OrderedDict([('b', 2), ('c', 3), ('d', 4), ('a', 1)]) OrderedDict([('d', 4), ('b', 2), ('c', 3), ('a', 1)]) d b c a
Set order of keys in dictionary - OrderedDict 1
from collections import OrderedDict
2 3 4 5 6 7 8
d = {} d['a'] = d['b'] = d['c'] = d['d'] = print(d)
1 2 3 4
9 10 11 12
planned_order = ('b', 'c', 'd', 'a') e = OrderedDict(sorted(d.items(), key=lambda x: planned_order.index(x[0]))) print(e)
13 14 15 16 17 18
print('-----') # Create index to value mapping dictionary from a list of values planned_order = ('b', 'c', 'd', 'a') plan = dict(zip(planned_order, range(len(planned_order)))) print(plan)
19 20 21
1 2 3 4 5
f = OrderedDict(sorted(d.items(), key=lambda x: plan[x[0]])) print(f)
{'a': 1, 'b': 2, 'c': 3, 'd': 4} OrderedDict([('b', 2), ('c', 3), ('d', 4), ('a', 1)]) ----{'b': 0, 'c': 1, 'd': 2, 'a': 3} OrderedDict([('b', 2), ('c', 3), ('d', 4), ('a', 1)])
Exercise: count characters Given a long text, count how many times each character appears?
202
Dictionary (hash) 1 2 3 4
203
text = """ This is a very long text. OK, maybe it is not that long after all. """
Extra credit: Change the code so it will be able to count characters of a file.
Exercise: count words Part of the code: 1
words = ['Wombat', 'Rhino', 'Sloth', 'Tarantula', 'Sloth', 'Rhino', 'Sloth']
Expected output: (the order is not important) 1 2 3 4
Wombat:1 Rhino:2 Sloth:3 Tarantula:1
Exercise: count words from a file Given a file with words and spaces and newlines only, count how many times each word appears. 1 2 3 4 5
Lorem ipsum dolor qui ad labor ad labor sint dolor tempor incididunt ut labor ad do\ lore lorem ad Ut labor ad dolor lorem qui ad ut labor ut ad commodo commodo Lorem ad dolor in reprehenderit in lorem ut labor ad dolore eu in labor dolor sint occaecat ad labor proident sint in in qui labor ad dolor ad in ad labor
• Based on Lorem Ipsum⁸⁸ Expected result for the above file:
⁸⁸https://www.lipsum.com/
Dictionary (hash) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
204
ad 13 commodo 2 dolor 6 dolore 2 eu 1 in 6 incididunt 1 ipsum 1 labor 10 lorem 5 occaecat 1 proident 1 qui 3 reprehenderit 1 sint 3 tempor 1 ut 5
Exercise: Apache log Every web server logs the visitors and their requests in a log file. The Apache web server has a log file similar to the following file. (Though I have trimmed the lines for the exercise.) Each line is a “hit”, a request from the browser of a visitor. Each line starts with the IP address of the visitor. e.g. 217.0.22.3. Given sucha a log file from Apache, report how many hits (line were from each IP address. 1 2 3 4 5 6 7 8 9 10 11 12 13
127.0.0.1 - - [10/Apr/2007:10:39:11] "GET / HTTP/1.1" 500 606 "-" 127.0.0.1 - - [10/Apr/2007:10:39:11] "GET /favicon.ico HTTP/1.1" 200 766 "-" 139.12.0.2 - - [10/Apr/2007:10:40:54] "GET / HTTP/1.1" 500 612 "-" 139.12.0.2 - - [10/Apr/2007:10:40:54] "GET /favicon.ico HTTP/1.1" 200 766 "-" 127.0.0.1 - - [10/Apr/2007:10:53:10] "GET / HTTP/1.1" 500 612 "-" 127.0.0.1 - - [10/Apr/2007:10:54:08] "GET / HTTP/1.0" 200 3700 "-" 127.0.0.1 - - [10/Apr/2007:10:54:08] "GET /style.css HTTP/1.1" 200 614 127.0.0.1 - - [10/Apr/2007:10:54:08] "GET /img/pti-round.jpg HTTP/1.1" 200 17524 127.0.0.1 - - [10/Apr/2007:10:54:21] "GET /unix_sysadmin.html HTTP/1.1" 200 3880 217.0.22.3 - - [10/Apr/2007:10:54:51] "GET / HTTP/1.1" 200 34 "-" 217.0.22.3 - - [10/Apr/2007:10:54:51] "GET /favicon.ico HTTP/1.1" 200 11514 "-" 217.0.22.3 - - [10/Apr/2007:10:54:53] "GET /cgi/pti.pl HTTP/1.1" 500 617 127.0.0.1 - - [10/Apr/2007:10:54:08] "GET / HTTP/0.9" 200 3700 "-"
205
Dictionary (hash) 14 15 16 17 18 19 20 21
217.0.22.3 - - [10/Apr/2007:10:58:27] "GET / HTTP/1.1" 200 3700 "-" 217.0.22.3 - - [10/Apr/2007:10:58:34] "GET /unix.html HTTP/1.1" 200 3880 217.0.22.3 - - [10/Apr/2007:10:58:45] "GET /talks/read.html HTTP/1.1" 404 311 127.0.0.1 - - [10/Apr/2007:10:54:08] "GET /img/pti-round.jpg HTTP/1.1" 200 17524 127.0.0.1 - - [10/Apr/2007:10:54:08] "GET /img/pti-round.jpg HTTP/1.1" 200 17524 127.0.0.1 - - [10/Apr/2007:10:54:21] "GET /unix_sysadmin.html HTTP/1.1" 200 3880 127.0.0.1 - - [10/Apr/2007:10:54:21] "GET /unix_sysadmin.html HTTP/1.1" 200 3880 217.0.22.3 - - [10/Apr/2007:10:54:51] "GET / HTTP/1.1" 200 34 "-"
Expected output: 1 2 3
127.0.0.1 139.12.0.2 217.0.22.3
12 2 7
Exercise: Combine lists again See the same exercise in the previous chapter.
Exercise: counting DNA bases Given a sequence like this: “ACTNGTGCTYGATRGTAGCYXGTN”, print out the distribution of the elemnts to get the following result: 1 2 3 4 5 6 7 8
A C G N R T X Y
3 3 6 2 1 6 1 2
-
12.50 12.50 25.00 8.33 4.17 25.00 4.17 8.33
% % % % % % % %
Exercise: Count Amino Acids • Each sequence consists of many repetition of the 4 bases represented by the ACTG characters. • There are 64 codons (sets of 3 bases following each other) • There are 20 Amino Acids⁸⁹ each of them are represented by 3 bases. ⁸⁹https://en.wikipedia.org/wiki/Amino_acid
Dictionary (hash)
206
• Some of the Amino Acids can be represented in multiple ways, represented in the [Codon Table] (https://en.wikipedia.org/wiki/DNA_codon_table)(For example Histidine can be encoded by both CAU, CAC) • We have a DNA sequence • Count the Amino acids from the sequence. (For our purposes feel free to generate a DNA sequence with a random number generator.
Exercise: List of dictionaries Given the following file build a list of dictionaries where each dictionary represents one person. The keys in the dictionary are the names of the columns (fname, lname, born) the values are the respective values from each row.
7
fname,lname,born Graham,Chapman,8 January 1941 Eric,Idle,29 March 1943 Terry,Gilliam,22 November 1940 Terry,Jones,1 February 1942 John,Cleese,27 October 1939 Michael,Palin,5 May 1943
1
print(people[1]['fname']) # Eric
1 2 3 4 5 6
Exercise: Dictinoary of dictionaries Given the following file build a dictionary of dictionaries where each internal dictionary represents one person. The keys in the internal dictionaries are the names of the columns (fname, lname, born) the values are the respective values from each row. In the outer dictionary the keys are the (fname, lname) tuples. 1 2 3 4 5 6 7
fname,lname,born Graham,Chapman,8 January 1941 Eric,Idle,29 March 1943 Terry,Gilliam,22 November 1940 Terry,Jones,1 February 1942 John,Cleese,27 October 1939 Michael,Palin,5 May 1943
Dictionary (hash) 1
207
print(people[('Eric', 'Idle')]['born']) # 29 March 1943
Exercise: Age limit with dictionaries • Ask the user what is their age and in which country are they located. • Tell them if they can legally drink alcohol. • See the Legal drinking age⁹⁰ list. • Given a file like the following create a new file with a third column in which you write “yes”, or “no” depending if the person can legally drink alcohol in that country.
Solution: count characters 1 2 3 4
text = """ This is a very long text. OK, maybe it is not that long after all. """
5 6 7
# print(text) count = {}
8 9 10 11 12 13 14 15
for char in text: if char == '\n': continue if char not in count: count[char] = 1 else: count[char] += 1
16 17 18
for key in sorted( count.keys() ): print("'{}' {}".format(key, count[key]))
• We need to store the counter somewhere. We could use two lists for that, but that would give a complex solution that runs in O(n**2) time. • Besides, we are in the chapter about dictionaries so probably we better use a dictionary. • In the count dictionary we each key is going to be one of the characters and the respective value will be the number of times it appeared. • So if out string is “aabx” then we’ll end up with ⁹⁰https://en.wikipedia.org/wiki/Legal_drinking_age
Dictionary (hash) 1
{ "a": 2, "b": 1, "x": 1,
2 3 4 5
208
}
• The for in loop on a string will iterate over it character by charter (even if we don’t call our variable char. • We check if the current character is a newline \n and if it we call continue to skip the rest of the iteration. We don’t want to count newlines. • Then we check if we have already seen this character. That is, it is already one of the keys in the count dictionary. If not yet, then we add it and put 1 as the values. After all we saw one copy of this character. If we have already seen this character (we get to the else part) then we increment the counter for this character. • We are done now with the data collection. • In the second loop we go over the keys of the dictionary, that is the characters we have encountered. We sort them in ASCII order. • Then we print each one of them and the respective value, the number of times the character was found.
Default Dict 1
counter = {}
2 3
word = 'eggplant'
4 5 6
1 2 3 4
counter[word] += 1 # counter[word] = counter[word] + 1
Traceback (most recent call last): File "counter.py", line 5, in counter[word] += 1 KeyError: 'eggplant'
Dictionary (hash) 1
counter = {}
2 3
word = 'eggplant'
4 5 6 7
if word not in counter: counter[word] = 0 counter[word] += 1
8 9
print(counter)
1
{'eggplant': 1}
1
from collections import defaultdict
2 3
counter = defaultdict(int)
4 5
word = 'eggplant'
6 7
counter[word] += 1
8 9
print(counter)
1
defaultdict(, {'eggplant': 1})
Solution: count characters with default dict 1
from collections import defaultdict
2 3 4 5 6
text = """ This is a very long text. OK, maybe it is not that long after all. """
7 8 9
# print(text) count = defaultdict(int)
10 11 12 13
for char in text: if char == '\n': continue
209
Dictionary (hash) 14
210
count[char] += 1
15 16 17
for key in sorted( count.keys() ): print("'{}' {}".format(key, count[key]))
• The previous solution can be slightly improved by using defaultdict from the collections module. • count = defaultdict(int) creates an empty dictionary that has the special feature that if you try to use a key that does not exists, it pretends that it exists and that it has a value 0. • This allows us to remove the condition checking if the character was already seen and just increment the counter. The first time we encounter a charcter the dictionary will pretend that it was already there with value 0 so everying will work out nicely.
Solution: count words 1
words = ['Wombat', 'Rhino', 'Sloth', 'Tarantula', 'Sloth', 'Rhino', 'Sloth']
2 3 4 5 6 7
counter = {} for word in words: if word not in counter: counter[word] = 0 counter[word] += 1
8 9 10
1
for word in counter: print("{}:{}".format(word, counter[word]))
from collections import Counter
2 3
words = ['Wombat', 'Rhino', 'Sloth', 'Tarantula', 'Sloth', 'Rhino', 'Sloth']
4 5 6 7
cnt = Counter() for word in words: cnt[word] += 1
8 9 10 11
print(cnt) for w in cnt.keys(): print("{}:{}".format(w, cnt[w]))
Dictionary (hash) 1
from collections import defaultdict
2 3
words = ['Wombat', 'Rhino', 'Sloth', 'Tarantula', 'Sloth', 'Rhino', 'Sloth']
4 5 6 7
dd = defaultdict(lambda : 0) for word in words: dd[word] += 1
8 9 10 11
print(dd) for word in dd.keys(): print("{}:{}".format(word, dd[word]))
Solution: count words in file 1
import sys
2 3 4 5 6
filename = 'README' if len(sys.argv) > 1: filename = sys.argv[1] print(filename)
7 8
count = {}
9 10 11 12 13 14 15 16 17 18
with open(filename) as fh: for full_line in fh: line = full_line.rstrip('\n') line = line.lower() for word in line.split(): if word == '': continue if word not in count: count[word] = 0
19 20
count[word] += 1
21 22 23
for word in sorted(count): print("{:13} {:>2}".format(word, count[word]))
Solution: Apache log
211
Dictionary (hash) 1
filename = 'examples/apache_access.log'
2 3
count = {}
4 5 6 7 8 9 10 11 12
with open(filename) as fh: for line in fh: space = line.index(' ') ip = line[0:space] if ip in count: count[ip] += 1 else: count[ip] = 1
13 14 15
for ip in count: print("{:16} {:>3}".format(ip, count[ip]))
Solution: Combine lists again 1 2 3 4 5 6 7 8
c = {} with open('examples/files/a.txt') as fh: for line in fh: k, v = line.rstrip("\n").split("=") if k in c: c[k] += int(v) else: c[k] = int(v)
9 10 11 12 13 14 15 16
with open('examples/files/b.txt') as fh: for line in fh: k, v = line.rstrip("\n").split("=") if k in c: c[k] += int(v) else: c[k] = int(v)
17 18 19 20 21
with open('out.txt', 'w') as fh: for k in sorted(c.keys()): fh.write("{}={}\n".format(k, c[k]))
Solution: counting DNA bases
212
Dictionary (hash) 1 2 3 4 5 6
seq = count for c if
"ACTNGTGCTYGATRGTAGCYXGTN" = {} in seq: c not in count: count[c] = 0 count[c] += 1
7 8 9
for c in sorted(count.keys()): print("{} {} - {:>5.2f} %".format(c, count[c], 100 * count[c]/len(seq)))
10 11 12
# >5 is the right alignment of 5 places # .2f is the floating point with 2 digits after the floating point
Solution: Count Amino Acids Generate random DNA sequence 1 2
import sys import random
3 4 5 6
if len(sys.argv) != 2: exit("Need a number") count = int(sys.argv[1])
7 8 9 10 11
1
dna = [] for _ in range(count): dna.append(random.choice(['A', 'C', 'T', 'G'])) print(''.join(dna))
dna = 'CACCCATGAGATGTCTTAACGCTGCTTTCATTATAGCCG'
2 3 4 5 6 7 8 9 10 11 12
aa_by_codon 'ACG' : 'CAC' : 'CAU' : 'CCA' : 'CCG' : 'GAT' : 'GTC' : 'TGA' : 'TTA' :
= { '?', 'Histidin', 'Histidin', 'Proline', 'Proline', '?', '?', '?', '?',
213
Dictionary (hash)
'CTG' 'CTT' 'TCA' 'TAG' #...
13 14 15 16 17 18
: : : :
'?', '?', '?', '?',
}
19 20
count = {}
21 22 23 24 25 26 27 28
for i in range(0, len(dna)-2, 3): codon = dna[i:i+3] #print(codon) aa = aa_by_codon[codon] if aa not in count: count[aa] = 0 count[aa] += 1
29 30 31
for aa in sorted(count.keys()): print("{} {}".format(aa, count[aa]))
Do not change dictionary in loop 1 2 3 4
user = { 'fname': 'Foo', 'lname': 'Bar', }
5 6 7 8
for k in user.keys(): user['email'] = '[email protected]' print(k)
9 10
print('-----')
11 12 13 14
for k in user: user['birthdate'] = '1991' print(k)
15 16 17 18 19 20
# # # # #
lname fname ----lname Traceback (most recent call last):
214
Dictionary (hash) 21 22 23
# File "examples/dictionary/change_in_loop.py", line 13, in # for k in user: # RuntimeError: dictionary changed size during iteration
215
Sets sets • Sets in Python are used when we are primarily interested in operations that we know from the set theory⁹¹. • See also the Venn diagrams⁹². • In day to day speach we often use the word “group” instead of “set” even though they are not the same. • What are the common elements of two set (two groups). • Is one group (set) the subset of the other? • What are all the elements that exist in both groups (sets)? • What are the elements that exist in exactly one of the groups (sets)?
set operations • • • • • •
set issubset intersection symmetric difference union relative complement
• stdtypes: set⁹³ ⁹¹https://en.wikipedia.org/wiki/Set_theory ⁹²https://en.wikipedia.org/wiki/Venn_diagram ⁹³http://docs.python.org/library/stdtypes.html#set
Sets
Creating a set 1 2 3
things = set(['table', 'chair', 'door', 'chair', 'chair']) print(things) print(type(things))
4 5 6
if 'table' in things: print("has table")
7 8 9
1 2 3 4
other = {'table', 'chair', 'door'} print(type(other))
{'door', 'table', 'chair'}
has table
Creating an empty set 2
objects = set() print(objects)
1
set()
1
Adding an element to a set (add) 1 2
objects = set() print(objects)
3 4 5
objects.add('Mars') print(objects)
6 7 8
objects.add('Mars') print(objects)
9 10 11
objects.add('Neptun') print(objects)
217
218
Sets 1 2 3 4
set() {'Mars'} {'Mars'} {'Neptun', 'Mars'}
Merging one set into another set (update) 1
set(['Neptun', 'Mars'])
2 3 4
objects = set(['Mars', 'Jupiter', 'Saturn']) internal = set(['Mercury', 'Venus', 'Earth', 'Mars'])
5 6 7 8
objects.update(internal) print(objects) print(internal)
9 10 11 12 13 14 15
1 2 3 4
objects = set(['Mars', 'Jupiter', 'Saturn']) internal = set(['Mercury', 'Venus', 'Earth', 'Mars']) internal.update(objects) print(objects) print(internal)
{'Mars', {'Mars', {'Mars', {'Mars',
'Venus', 'Mercury', 'Earth', 'Saturn', 'Jupiter'} 'Earth', 'Venus', 'Mercury'} 'Saturn', 'Jupiter'} 'Venus', 'Mercury', 'Earth', 'Saturn', 'Jupiter'}
set intersection
219
Sets 1 2
english = set(['door', 'car', 'lunar', 'era']) spanish = set(['era', 'lunar', 'hola'])
3 4 5
print('english: ', english) print('spanish: ', spanish)
6 7 8
both = english.intersection(spanish) print(both)
• intersection returns the elements that are in both sets.
1 2 3
english: {'car', 'lunar', 'era', 'door'} spanish: {'lunar', 'era', 'hola'} {'lunar', 'era'}
set subset 1 2
english = set(['door', 'car', 'lunar', 'era']) spanish = set(['era', 'lunar', 'hola'])
3 4
words = set(['door', 'lunar'])
5 6 7 8
print('issubset: ', words.issubset( english )) print('issubset: ', words.issubset( spanish ))
220
Sets 1 2
issubset: issubset:
True False
set symmetric difference 1 2
english = set(['door', 'car', 'lunar', 'era']) spanish = set(['era', 'lunar', 'hola'])
3 4 5
diff = english.symmetric_difference(spanish) print('symmetric_difference: ', diff)
• Symmetric difference contains all the elements in either one of the sets, but not in both. “the ears of the elephant”. 1
symmetric_difference:
{'door', 'hola', 'car'}
set union 1 2
english = set(['door', 'car', 'lunar', 'era']) spanish = set(['era', 'lunar', 'hola'])
3 4
all_the_words = english.union(spanish)
5 6 7 8
print(english) print(spanish) print(all_the_words)
9 10 11
# x = english + spanish # TypeError: unsupported operand type(s) for +: 'set' and 's\ et'
Sets 1 2 3
{'era', 'door', 'lunar', 'car'} {'era', 'hola', 'lunar'} {'era', 'door', 'car', 'hola', 'lunar'}
set relative complement 1 2
english = set(['door', 'car', 'lunar', 'era']) spanish = set(['era', 'lunar', 'hola'])
3 4 5 6
eng = english - spanish spa = spanish - english
7 8 9
print(spa) print(eng)
10 11 12
1 2 3 4
print(english) print(spanish)
{'hola'} {'door', 'car'} {'door', 'era', 'car', 'lunar'} {'hola', 'era', 'lunar'}
221
Sets
222
Functions (subroutines) Why use functions? There are two main reasons to use functions. One of the is code reuse. Instead of copy-paste-ing snippets of code that does the same in multiple areas in the application, we can create a function with a single copy of the code and call it from multiple location. Having functions can also make the code easier to understand, easier to test and to maintain. The functions are supposed to be relatively short, each function dealing with one issue, with one concern. They should have well defined input and output and without causing side-effects. There are no clear rules, but the suggestion is that function be somewhere between 4-30 lines of code.
• Code reuse - DRY - Don’t Repeate Yourself⁹⁴ • Small units of code. (One thought, single responsibility) Easier to understand, test, and maintain.
Defining simple function 1 2 3
def add(x, y): z = x + y return z
4 5 6
a = add(2, 3) print(a) # 5
7 8 9
q = add(23, 19) print(q) # 42
⁹⁴https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
Functions (subroutines)
The function definition starts with the word “dev” followed by the name of the function (“add” in our example), followed by the list of parameters in a pair of parentheses, followed by a colon “:”. Then the body of the function is indented to the right. The depth of indentation does not matter but it must be the same for all the lines of the function. When we stop the indentation and start a new expression on the first column, that’s what tells Python that the function defintion has ended.
Passing positional parameters to a function 1 2 3 4 5 6
def sendmail(From, To, Subject, Content): print('From:', From) print('To:', To) print('Subject:', Subject) print('') print(Content)
7 8 9 10 11
sendmail('[email protected]', '[email protected]', 'self message', 'Has some content too')
Positional parameters.
Function parameters can be named
224
Functions (subroutines) 1 2 3 4 5 6
def sendmail(From, To, Subject, Content): print('From:', From) print('To:', To) print('Subject:', Subject) print('') print(Content)
7 8 9 10 11 12 13
sendmail( Subject = 'self message', Content = 'Has some content too', From = '[email protected]', To = '[email protected]', )
The parameters of every function can be passed either as positional parameters or as named parameters.
Mixing positional and named parameters 1 2 3 4 5 6
def sendmail(From, To, Subject, Content): print('From:', From) print('To:', To) print('Subject:', Subject) print('') print(Content)
7 8 9 10 11 12 13
sendmail( Subject = 'self message', Content = 'Has some content too', To = '[email protected]', '[email protected]', )
225
Functions (subroutines) 1 2 3 4 5 6
def sendmail(From, To, Subject, Content): print('From:', From) print('To:', To) print('Subject:', Subject) print('') print(Content)
7 8 9 10 11 12 13
1 2 3 4
sendmail( '[email protected]', Subject = 'self message', Content = 'Has some content too', To = '[email protected]', )
File "examples/functions/named_and_positional_params.py", line 14 '[email protected]', ^ SyntaxError: positional argument follows keyword argument
Default values, optional parameters, optional parameters 1 2 3 4 5 6 7 8 9
def prompt(question, retry=3): print(question) print(retry) #while retry > 0: # inp = input('{} ({}): '.format(question, retry)) # if inp == 'my secret': # return True # retry -= 1 #return False
10 11
prompt("Type in your password")
12 13
prompt("Type in your secret", 1)
14 15
prompt("Hello", retry = 7)
16 17
prompt(retry = 42, question = "Is it you?")
226
Functions (subroutines) 1 2 3 4 5 6 7 8
Type in your password 3 Type in your secret 1 Hello 7 Is it you? 42
Function parameters can have default values. In such case the parameters are optional. In the function declaration, the parameters with the default values must come last. In the call, the order among these arguments does not matter, and they are optional anyway.
Default value in first param 1 2
1 2 3 4
def add(x=2, y): print("OK")
File "default_first.py", line 2 def add(x=2, y): ^ SyntaxError: non-default argument follows default argument
Several defaults, using names Parameters with defaults must come at the end of the parameter declaration.
227
228
Functions (subroutines) 1 2
def f(a, b=2, c=3): print(a, b , c)
3 4 5 6 7
f(1) f(1, b=0) f(1, c=0) f(1, c=0, b=5)
# # # #
1 1 1 1
2 0 2 5
3 3 0 0
8 9 10 11
# f(b=0, 1) # would generate: # SyntaxError: non-keyword arg after keyword arg
12 13
1 2 3
1 2 3 4
f(b=0, a=1)
# 1 0 3
def f(a = 2, b): print(a) print(b)
File "examples/functions/named_and_positional_bad.py", line 2 def f(a = 2, b): ^ SyntaxError: non-default argument follows default argument
There can be several parameters with default values. They are all optional and can be given in any order after the positional arguments.
Arbitrary number of arguments * The values arrive as tuple.
Functions (subroutines) 1 2 3 4 5 6 7
def mysum(*numbers): print(numbers) print(type(numbers)) total = 0 for s in numbers: total += s return total
8 9 10 11
print(mysum(1)) print(mysum(1, 2)) print(mysum(1, 1, 1))
12 13
x = [2, 3, 5, 6]
14 15
print(mysum(*x))
16 17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
mysum(x)
(1,)
1 (1, 2)
3 (1, 1, 1)
3 (2, 3, 5, 6)
16 ([2, 3, 5, 6],)
Traceback (most recent call last): File "examples/functions/sum.py", line 17, in mysum(x) File "examples/functions/sum.py", line 6, in mysum total += s TypeError: unsupported operand type(s) for +=: 'int' and 'list'
Fixed parmeters before the others
229
230
Functions (subroutines)
The *numbers argument can be preceded by any number of regular arguments
1 2 3 4 5 6 7 8
def mysum(op, *numbers): print(numbers) if op == '+': total = 0 elif op == '*': total = 1 else: raise Exception('invalid operator {}'.format(op))
9 10 11 12 13 14
for s in numbers: if op == '+': total += s elif op == '*': total *= s
15 16
return total
17 18 19 20 21
1 2 3 4 5 6 7 8
print(mysum('+', print(mysum('+', print(mysum('+', print(mysum('*',
1)) 1, 2)) 1, 1, 1)) 1, 1, 1))
(1,) 1 (1, 2) 3 (1, 1, 1) 3 (1, 1, 1) 1
Arbitrary key-value pairs in parameters **
Functions (subroutines) 1 2
def f(**kw): print(kw)
3 4
f(a = 23, b = 12)
1
{'a': 23, 'b': 12}
Extra key-value pairs in parameters 1 2 3
def f(name, **kw): print(name) print(kw)
4 5
f(name="Foo", a = 23, b = 12)
6 7 8
1 2
# Foo # {'a': 23, 'b': 12}
Foo {'a': 23, 'b': 12}
Every parameter option 1 2 3 4 5
def f(op, count = 0, *things, **kw): print(op) print(count) print(things) print(kw)
6 7
f(2, 3, 4, 5, a = 23, b = 12)
8 9 10 11 12
# # # #
2 3 (4, 5) {'a': 23, 'b': 12}
Duplicate declaration of functions (multiple signatures)
231
Functions (subroutines) 1 2
232
def add(x, y): return x*y
3 4 5
def add(x): return x+x
6 7
print(add(2))
# 4
8 9 10
1 2 3 4 5
add(2, 3) # TypeError: add() takes exactly 1 argument (2 given)
4 Traceback (most recent call last): File "examples/functions/duplicate_add.py", line 9, in add(2, 3) TypeError: add() takes 1 positional argument but 2 were given
The second declaration silently overrides the first declaration.
Pylint duplicate declaration • pylint⁹⁵ can find such problems, along with a bunch of others.
1
pylint -E duplicate_add.py
1
************* Module duplicate_add examples/functions/duplicate_add.py:4:0: E0102: function already defined line 1 (fun\ ction-redefined) examples/functions/duplicate_add.py:9:0: E1121: Too many positional arguments for fu\ nction call (too-many-function-args)
2 3 4 5
Return more than one value
⁹⁵http://www.pylint.org/
Functions (subroutines) 1 2 3 4
def calc(x, y): a = x+y b = x*y return a, b
5 6 7 8
z, q = calc(2, 3) print(z) print(q)
9 10 11 12
1 2 3
t = calc(4, 5) print(t)
5 6 (9, 20)
Recursive factorial 1
n! = n * (n-1) ... * 1
2 3 4
0! = 1 n! = n * (n-1)!
5 6 7
1 2 3 4
f(0) = 1 f(n) = n * f(n-1)
def f(n): if n == 0: return 1 return n * f(n-1)
5 6 7 8 9
print(f(1)) print(f(2)) print(f(3)) print(f(4))
# # # #
1 2 6 24
Recursive Fibonacci
233
234
Functions (subroutines) 1 2 3
1 2 3 4 5 6
fib(1) = 1 fib(2) = 1 fib(n) = fib(n-1) + fib(n-2)
def fib(n): if n == 1: return 1 if n == 2: return 1 return fib(n-1) + fib(n-2)
7 8 9
print(3, fib(3)) print(30, fib(30))
# 2 # 832040
Python also supports recursive functions.
Non-recursive Fibonacci 1 2 3 4 5 6 7 8 9
def fib(n): if n == 1: return [1] if n == 2: return [1, 1] fibs = [1, 1] for i in range(2, n): fibs.append(fibs[-1] + fibs[-2]) return fibs
10 11 12 13 14
print(fib(1)) print(fib(2)) print(fib(3)) print(fib(10))
# # # #
[1] [1, 1] [1, 1, 2] [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Unbound recursion • In order to protect us from unlimited recursion, Python limits the depth of recursion:
Functions (subroutines) 1 2 3
def recursion(n): print(f"In recursion {n}") recursion(n+1)
4 5
recursion(1)
1
... In recursion 995 In recursion 996 Traceback (most recent call last): File "recursion.py", line 7, in recursion(1) File "recursion.py", line 5, in recursion recursion(n+1) File "recursion.py", line 5, in recursion recursion(n+1) File "recursion.py", line 5, in recursion recursion(n+1) [Previous line repeated 992 more times] File "recursion.py", line 4, in recursion print(f"In recursion {n}") RecursionError: maximum recursion depth exceeded while calling a Python object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Variable assignment and change - Immutable Details showed on the next slide 1 2 3 4 5 6 7
a = 42 b = a print(a) print(b) a = 1 print(a) print(b)
# # # #
number or string This is a copy 42 42
# 1 # 42
8 9 10 11 12 13 14
a = (1, 2) # tuple b = a # this is a copy print(a) # (1, 2) print(b) # (1, 2) # a[0] = 42 TypeError: 'tuple' object does not support item assignment a = (3, 4, 5)
235
Functions (subroutines) 15 16
print(a) print(b)
# (3, 4, 5) # (1, 2)
Variable assignment and change - Mutable 1 2
a = [5, 6] b = a
3 4 5 6 7 8 9
print(a) print(b) a[0] = 1 print(a) print(b)
# # # # #
this is a copy of the *reference* only if we change the list in a, it will change the list connected to b as well [5, 6] [5, 6]
# [1, 6] # [1, 6]
10 11 12 13 14 15 16 17 18 19 20
a = {'name' : 'Foo'} b = a # this is a copy of the *reference* only # if we change the dictionary in a, it will # change the dictionary connected to b as well print(a) # {'name' : 'Foo'} print(b) # {'name' : 'Foo'} a['name'] = 'Jar Jar' print(a) # {'name' : 'Jar Jar'} print(b) # {'name' : 'Jar Jar'}
Parameter passing of functions 1
x = 3
2 3 4 5
def inc(n): n += 1 return n
6 7 8 9
print(x) print(inc(x)) print(x)
# 3 # 4 # 3
Passing references
236
237
Functions (subroutines) 1
numbers = [1, 2, 3]
2 3 4
def update(x): x[0] = 23
5 6 7 8
def change(y): y = [5, 6] return y
9 10
print(numbers)
# [1, 2, 3]
update(numbers) print(numbers)
# [23, 2, 3]
11 12 13 14 15 16
print(change(numbers)) # [5, 6] print(numbers) # [23, 2, 3]
Function documentation 1 2 3 4 5 6
def f(name): """ The documentation should have more than one lines. """ print(name)
7 8 9 10
f("hello") print(f.__doc__)
Immediately after the definition of the function, you can add a string - it can be a “”” string to spread multiple lines that will include the documentation of the function. This string can be accessed via the doc (2+2 underscores) attribute of the function. Also, if you ‘import’ the file - as a module - in the interactive prompt of Python, you will be able to read this documentation via the help() function. help(mydocs) or help(mydocs.f) in the above case.
Functions (subroutines)
Sum ARGV 1
import sys
2 3 4 5 6 7 8
def mysum(*numbers): print(numbers) total = 0 for s in numbers: total += s return total
9 10 11 12
v = [int(x) for x in sys.argv[1:] ] r = mysum( *v ) print(r)
Copy-paste code 1 2 3
a = [2, 3, 93, 18] b = [27, 81, 11, 35] c = [32, 105, 1]
4 5 6 7 8
total_a = 0 for v in a: total_a += v print("sum of a: {} average of a: {}".format(total_a, total_a / len(a)))
9 10 11 12 13
total_b = 0 for v in b: total_b += v print("sum of b: {} average of b: {}".format(total_b, total_b / len(b)))
14 15 16 17 18
1 2 3
total_c = 0 for v in c: total_c += v print("sum of c: {} average of c: {}".format(total_c, total_c / len(a)))
sum of a: 116 average of a: 29.0 sum of b: 154 average of b: 38.5 sum of c: 138 average of c: 34.5
Did you notice the bug?
238
Functions (subroutines)
Copy-paste code fixed 1 2 3
a = [2, 3, 93, 18] b = [27, 81, 11, 35] c = [32, 105, 1]
4 5 6 7 8 9
def calc(numbers): total = 0 for v in numbers: total += v return total, total / len(numbers)
10 11 12
total_a, avg_a = calc(a) print("sum of a: {} average of a: {}".format(total_a, avg_a))
13 14 15
total_b, avg_b = calc(b) print("sum of b: {} average of b: {}".format(total_b, avg_b))
16 17 18 19
1 2 3
total_c, avg_c = calc(c) print("sum of c: {} average of c: {}".format(total_c, avg_c))
sum of a: 116 average of a: 29.0 sum of b: 154 average of b: 38.5 sum of c: 138 average of c: 46.0
Copy-paste code further improvement 1 2 3 4 5
data = { 'a': [2, 3, 93, 18], 'b': [27, 81, 11, 35], 'c': [32, 105, 1], }
6 7 8 9 10 11 12
def calc(numbers): total = 0 for v in numbers: total += v return total, total / len(numbers)
239
240
Functions (subroutines) 13 14 15 16 17 18
total = {} avg = {} for name, numbers in data.items(): total[name], avg[name] = calc(numbers) print("sum of {}: {} average of {}: {}".format(name, total[name], name, avg[name]\ ))
Palindrome An iterative and a recursive solution 1 2 3 4 5 6
def is_palindrome(s): if s == '': return True if s[0] == s[-1]: return is_palindrome(s[1:-1]) return False
7 8 9 10 11 12
def iter_palindrome(s): for i in range(0, int(len(s) / 2)): if s[i] != s[-(i+1)]: return False return True
13 14 15 16 17 18 19
print(is_palindrome('')) print(is_palindrome('a')) print(is_palindrome('ab')) print(is_palindrome('aa')) print(is_palindrome('aba')) print(is_palindrome('abc'))
# # # # # #
True True False True True False
20 21 22 23 24 25 26 27
print() print(iter_palindrome('')) print(iter_palindrome('a')) print(iter_palindrome('ab')) print(iter_palindrome('aa')) print(iter_palindrome('aba')) print(iter_palindrome('abc'))
# # # # # #
True True False True True False
Exercise: statistics Write a function that will accept any number of numbers and return a list of values:
Functions (subroutines)
• • • •
The sum Average Minimum Maximum
Exercise: recursive Give a bunch of files that has list of requirement in them. Process them recursively and print the resulting full list of requirements 1 2 3
1 2
b c d
e d
2
f g
1
$ python traversing_dependency_tree.py a
1
2 3 4 5 6 7 8 9 10
Processing Processing Processing Processing Processing Processing Processing Processing
a b e d c f g d
Exercise: Tower of Hanoi Tower of Hanoi⁹⁶ ⁹⁶https://en.wikipedia.org/wiki/Tower_of_Hanoi
241
242
Functions (subroutines)
Exercise: Merge and Bubble sort • Implement bubble sort⁹⁷ • Implement merge sort⁹⁸
Exercise: Refactor previous solutions to use functions • Go over all of the previous exercises and their solutions (e.g. the games) • Take one (or more if you like this exercise) and change them to use functions. • If possible make sure you don’t have any variable definitions outside of the functions and that each function has a single job to do.
Solution: statistics 1 2
def stats(*numbers): total = 0
3 4 5 6
average = None minx = None maxx = None
# there might be better solutions here!
7 8 9 10 11 12 13 14 15
for val in numbers: total += val if minx == None: minx = maxx = val if minx > val: minx = val if maxx < val: maxx = val
16 17 18
if len(numbers): average = total / len(numbers)
19 20 21
return total, average, minx, maxx
22 23 24
ttl, avr, smallest, largest = stats(3, 5, 4) ⁹⁷https://en.wikipedia.org/wiki/Bubble_sort ⁹⁸https://en.wikipedia.org/wiki/Merge_sort
Functions (subroutines) 25 26 27 28 29
print(ttl) print(avr) print(smallest) print(largest)
Solution: recursive 1 2
import sys import os
3 4 5
if len(sys.argv) < 2: exit("Usage: {} NAME".format(sys.argv[0]))
6 7
start = sys.argv[1]
8 9 10
def get_dependencies(name): print("Processing {}".format(name))
11 12 13 14 15
deps = set(name) filename = name + ".txt" if not os.path.exists(filename): return deps
16 17 18 19 20 21
with open(filename) as fh: for line in fh: row = line.rstrip("\n") deps.add(row) deps.update( get_dependencies(row) )
22 23
return deps
24 25 26
dependencies = get_dependencies(start) print(dependencies)
Solution: Tower of Hanoi
243
244
Functions (subroutines) 1 2 3 4
def check(): for loc in hanoi.keys(): if hanoi[loc] != sorted(hanoi[loc], reverse=True): raise Exception(f"Incorrect order in {loc}: {hanoi[loc]}")
5 6 7 8
def move(depth, source, target, helper): if depth > 0: move(depth-1, source, helper, target)
9 10 11 12 13 14
val = hanoi[source].pop() hanoi[target].append(val) print(f"Move {val} from {source} to {target} B:{str(hanoi['B']):10} C:{str(hanoi['C']):10}") check()
15 16 17
move(depth-1, helper, target, source) check()
18 19 20 21 22 23
hanoi = { 'A': [4, 3, 2, 1], 'B': [], 'C': [], }
24 25 26 27
check() move(len(hanoi['A']), 'A', 'C', 'B') check()
Solution: Merge and Bubble sort 1 2 3 4
def recursive_bubble_sort(data): data = data[:] if len(data) == 1: return data
5 6 7 8 9 10 11 12
last = data.pop() sorted_data = recursive_bubble_sort(data) for i in range(len(sorted_data)): if last > sorted_data[i]: sorted_data.insert(i, last) break else:
Status A:{str(hanoi['A']):10}\
Functions (subroutines) 13 14
sorted_data.append(last) return sorted_data
15 16 17 18 19 20 21 22
def iterative_bubble_sort(data): data = data[:] for end in (range(len(data)-1, 0, -1)): for i in range(end): if data[i] < data[i+1]: data[i], data[i+1] = data[i+1], data[i] return data
23 24 25 26 27 28 29 30
old = [1, 5, 2, 4, 8] new1 = recursive_bubble_sort(old) new2 = iterative_bubble_sort(old) print(old) print(new1) print(new2)
245
Modules Before modules 1 2
def add(a, b): return a + b
3 4 5 6
z = add(2, 3) print(z)
# 5
Create modules A module is just a Python file with a set of functions that us usually not used by itself. For example the “my_calculator.py”.
1 2
def add(a, b): return a + b
A user made module is loaded exactly the same way as the built-in module. The functions defined in the module are used as if they were methods.
1
import my_calculator
2 3
z = my_calculator.add(2, 3)
4 5
print(z)
# 5
247
Modules
We can import specific functions to the current name space (symbol table) and then we don’t need to prefix it with the name of the file every time we use it. This might be shorter writing, but if we import the same function name from two different modules then they will overwrite each other. So I usually prefer loading the module as in the previous example.
1
from my_calculator import add
2 3
print(add(2, 3))
# 5
path to load modules from - The module search path 1. 2. 3. 4. 5.
The directory where the main script is located. The directories listed in PYTHONPATH environment variable. Directories of standard libraries. Directories listed in .pth files. The site-packages home of third-party extensions.
sys.path - the module search path 1
import sys
2 3
print(sys.path)
1
['/Users/gabor/work/training/python/examples/package', '/Users/gabor/python/lib/python2.7/site-packages/crypto-1.1.0-py2.7.egg', ... '/Library/Python/2.7/site-packages', '/usr/local/lib/python2.7/site-packages'] [Finished in 0.112s]
2 3 4 5
Flat project directory structure
Modules
If our executable scripts and our modules are all in the same directory then we don’t have to worry ad the directory of the script is included in the list of places where “import” is looking for the files to be imported.
1 2 3 4
project/ script_a.py script_b.py my_module.py
Absolute path If we would like to load a module that is not installed in one of the standard locations, but we know where it is located on our disk, we can set the “sys.path” to the absolute path to this directory. This works on the specific computer, but if you’d like to distribute the script to other computers you’ll have to make sure the module to be loaded is installed in the same location or you’ll have to update the script to point to the location of the module in each computer. Not an ideal solution.
1 2
import sys sys.path.insert(0, "/home/foobar/python/libs")
3 4
# import module_name
Relative path 1 2 3
../project_root/ bin/relative_path.py lib/my_module.py
248
249
Modules
We can use a directory structure that is more complex than the flat structure we had earlier. In this case the location of the modules relatively to the scripts is fixed. In this case it is “../lib”. We can compute the relative path in each of our scripts. That will ensure we pick up the right module every time we run the script. Regardless of the location of the whole project tree.
1
print("Importing my_module")
1
import os, sys
2 3
# import my_module
# ImportError: No module named my_module
4 5 6
print(__file__) # examples/sys/bin/relative_path.py project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
7 8 9 10
mypath = os.path.join(project_root, 'lib') print(mypath) # /Users/gabor/work/training/python/examples/sys/../lib sys.path.insert(0, mypath)
11 12
import my_module
# Importing my_module
Python modules are compiled When libraries are loaded they are automatically compiled to .pyc files. This provides moderate code-hiding and load-time speed-up. Not run-time speed-up. Starting from Python 3.2 the pyc files are saved in the __pycache__ directory.
How “import” and “from” work? 1. 2. 3. 4.
Find the file to load. Compile to bytecode if necessary and save the bytecode if possible. Run the code of the file loaded. Copy names from the imported module to the importing namespace.
Runtime loading of modules
250
Modules 1 2
def hello(): print("Hello World")
3 4
print("Loading mygreet")
1
print("Start running")
# Start running
import mygreet
# Loading mygreet
mygreet.hello()
# Hello World
print("DONE")
# DONE
2 3 4 5 6 7
Conditional loading of modules 1
import random
2 3 4
print("Start running") name = input("Your name:")
5 6 7 8 9 10
if name == "Foo": import mygreet mygreet.hello() else: print('No loading')
11 12 13
print("DONE")
Duplicate importing of functions
251
Modules 1 2
from mycalc import add print(add(2, 3)) # 5
3 4 5
from mymath import add print(add(2, 3)) # 6
6 7 8 9
from mycalc import add print(add(2, 3)) # 5
The second declaration silently overrides the first declaration. pylint⁹⁹ can find such problems, along with a bunch of others.
Script or library We can have a file with all the functions implemented and then launch the run() function only if the file was executed as a stand-alone script.
1 2
def run(): print("run in ", __name__)
3 4
print("Name space in mymodule.py ", __name__)
5 6 7
1 2 3
if __name__ == '__main__': run()
$ python mymodule.py Name space in mymodule.py run in __main__
__main__
Script or library - import
⁹⁹http://www.pylint.org/
Modules
If it is imported by another module then it won’t run automatically. We have to call it manually.
1
import mymodule
2 3 4
1 2 3 4
print("Name space in import_mymodule.py ", __name__) mymodule.run()
$ python import_mymodule.py Name space in mymodule.py mymodule Name space in import_mymodule.py __main__ run in mymodule
Script or library - from import 1
from mymodule import run
2 3 4
1 2 3 4
print("Name space in import_mymodule.py ", __name__) run()
$ python import_from_mymodule.py Name space in mymodule.py mymodule Name space in import_mymodule.py __main__ run in mymodule
assert to verify values
252
Modules 1 2
def add(x, y): return x * y
3 4 5 6 7 8
1 2 3 4 5 6
1 2
for x, y, z in [(2, 2, 4), (9, 2, 11), (2, 3, 5)]: print(f"add({x}, {y}) == {z}") if add(x, y) != z: raise Exception(f"add({x}, {y}) != {z}") #raise AssertionError
add(2, 2) == 4 add(9, 2) == 11 Traceback (most recent call last): File "examples/functions/raise_exception.py", line 7, in raise Exception(f"add({x}, {y}) != {z}") Exception: add(9, 2) != 11
def add(x, y): return x * y
3 4 5 6
1 2 3 4 5 6
for x, y, z in [(2, 2, 4), (9, 2, 11), (2, 3, 5)]: print(f"add({x}, {y}) == {z}") assert add(x, y) == z
add(2, 2) == 4 add(9, 2) == 11 Traceback (most recent call last): File "examples/functions/assert.py", line 6, in assert add(x, y) == z AssertionError
mycalc as a self testing module 1 2
1 2
import mycalc print(mycalc.add(19, 23))
$ python use_mycalc.py 42
253
Modules 1 2 3 4 5
def test_add(): print('Testing {}'.format(__file__)) assert add(1, 1) == 2 assert add(-1, 1) == 0 # assert add(-99, 1) == 0 # AssertionError
6 7 8
def add(a, b): return a + b
9 10 11
1 2
if __name__ == '__main__': test_add()
$ python mycalc.py Self testing mycalc.py
doctest 1 2 3 4 5 6 7 8 9
def fib(n): ''' Before the tests >>> fib(3) 2 >>> fib(10) 55 >>> [fib(n) for n in range(11)] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
10 11 12 13 14 15
>>> fib(11) 89 After the tests ''' values = [0, 1]
16 17 18
if n == 11: return 'bug'
19 20 21 22
while( n > len(values) -1 ): values.append(values[-1] + values[-2]) return values[n]
23 24
#if __name__ == "__main__":
254
255
Modules 25 26
# #
import doctest doctest.testmod()
1
python -m doctest fibonacci_doctest.py
1
python examples/functions/fibonacci_doctest.py
2 3 4 5 6 7 8 9 10 11 12 13 14
********************************************************************** File ".../examples/functions/fibonacci_doctest.py", line 12, in __main__.fib Failed example: fib(11) Expected: 89 Got: 'bug' ********************************************************************** 1 items had failures: 1 of 4 in __main__.fib ***Test Failed*** 1 failures.
doctest¹⁰⁰
Scope of import 1 2
1 2
def div(a, b): return a/b
from __future__ import print_function from __future__ import division
3 4
import mydiv
5 6
print(mydiv.div(3, 2))
# 1
print(3/2)
# 1.5
7 8
¹⁰⁰https://docs.python.org/3/library/doctest.html
256
Modules
The importing of functions, and the changes in the behavior of the compiler are file specific. In this case the change in the behavior of division is only visible in the division.py script, but not in the mydiv.py module.
Export import • • • •
1 2
from mod import a,b,_c - import ‘a’, ‘b’, and ‘_c’ from ‘mod’ from mod import * - import every name listed in all of ‘mod’ if all is available. from mod import * - import every name that does NOT start with _ (if all is not available) import mod - import ‘mod’ and make every name in ‘mod’ accessible as ‘mod.a’, and ‘mod._c’
def a(): return "in a"
3 4
b = "value of b"
5 6 7
def _c(): return "in _c"
8 9 10
1
def d(): return "in d"
from my_module import a,b,_c
2 3 4 5
print(a()) print(b) print(_c())
# in a # value of b # in _c
6 7 8 9 10 11
print(d()) # Traceback (most recent call last): # File ".../examples/modules/x.py", line 7, in # print(d()) # NameError: name 'd' is not defined
257
Modules 1
from my_module import *
2 3 4
print(a()) print(b)
# in a # value of b
print(d())
# in d
5 6 7 8 9
print(_c())
10 11 12 13 14
# Traceback (most recent call last): # File ".../examples/modules/y.py", line 9, in # print(_c()) # in _c # NameError: name '_c' is not defined
Export import with all 1
__all__ = ['a', '_c']
2 3 4
def a(): return "in a"
5 6
b = "value of b"
7 8 9
def _c(): return "in _c"
10 11 12
1
def d(): return "in d"
from my_module2 import *
2 3 4
print(a()) print(_c())
# in a # in _c
5 6
print(b)
7 8 9 10 11
# Traceback (most recent call last): # File ".../examples/modules/z.py", line 7, in # value of b # print(b) # NameError: name 'b' is not defined
258
Modules
import module 1
import my_module
2 3 4 5 6
print(my_module.a()) print(my_module.b) print(my_module._c()) print(my_module.d())
# # # #
in a value of b in _c in d
Execute at import time 1
import lib
2 3
print("Hello")
1
print("import lib")
2 3 4
1 2
def do_something(): print("do something")
import lib Hello
Import multiple times 1 2
import one import two
3 4
print("Hello")
1
import common print("loading one")
2
1 2
import common print("loading two")
Modules 1
print("import common")
1
import common loading one loading two Hello
2 3 4
259
Exercise: Number guessing Take the number guessing game from the earlier chapter and move the internal while() loop to a function. Once that’s done, move the function out to a separate file and use it as a module.
Exercies: Scripts and modules Take the number guessing game: if I run it as a script execute the whole game with repeated hidden numbers. If I load it as a module, then let me call the function that runs a single game with one hidden number. We should be able to even pass the hidden number as a parameter.
Exercise: Module my_sum • Create a file called my_simple_math.py with two functions: div(a, b), add(a, b), that will divide and add the two numbers respectively. • Add another two functions called test_div and test_add that will test the above two functions using assert. • Add code that will run the tests if someone execute python my_simple_math.py running the file as if it was a script. • Create another file called use_my_simple_math.py that will use the functions from my_math module to calculate 2 + 5 * 7 • Make sure when you run python use_my_simple_math.py the tests won’t run. • Add documentation to the “add” and “div” functions to examples that can be used with doctest. • Can you run the tests when the file is loaded as a module?
260
Modules
Exercise: Convert your script to module • Take one of your real script (from work). Create a backup copy. • Change the script so it can be import-ed as a module and then it won’t automatically execute anything, but that it still works when executed as a script. • Add a new function to it called self_test and in that function add a few test-cases to your code using ‘assert’. • Write another script that will load your real file as a module and will run the self_test. • Let me know what are the dificulties!
Exercise: Add doctests to your own code • Pick a module from your own code and create a backup copy. (from work) • Add a function called ‘self_test’ that uses ‘assert’ to test some of the real functions of the module. • Add code that will run the ‘self_test’ when the file is executed as a script. • Add documentation to one of the functions and convert the ‘assert’-based tests to doctests. • Convert the mechanism that executed the ‘self_test’ to run the doctests as well. • Let me know what are the dificulties!
Solution: Module my_sum 1 2 3 4 5 6
def div(a, b): ''' >>> div(8, 2) 4 ''' return a/b
7 8 9 10 11 12 13
def add(a, b): ''' >>> add(2, 2) 4 ''' return a * b
# bug added on purpose!
14 15 16 17 18
def test_div(): assert div(6, 3) == 2 assert div(0, 10) == 0 assert div(-2, 2) == -1
Modules 19
#assert div(10, 0) == ??
20 21 22 23
def test_add(): assert add(2, 2) == 4 #assert add(1, 1) == 2
24 25 26 27 28
1 2
if __name__ == "__main__": test_div() test_add()
import my_simple_math print(my_simple_math.my_sum(2, 3, 5))
3 4 5
print(dir(my_simple_math)) #my_sum_as_function.test_my_sum()
261
Regular Expressions What are Regular Expressions (aka. Regexes)? • • • • • •
1
An idea on how to match some pattern in some text. A tool/language that is available in many places. Has many different “dialects” Has many different modes of processing. The grand concept is the same. Uses the following symbols:
() [] {} . * + ? ^ $ | - \ \d \s \w \A \Z \1 \2 \3
What are Regular Expressions good for? • • • • • •
Decide if a string is part of a larger string. Validate the format of some value (string) (e.g. is it a decimal number?, is it a hex?) Find if there are repetitions in a string. Analyze a string and fetch parts of if given some loose description. Cut up a string into parts. Change parts of a string.
Examples 1
Is the input given by the user a number?
2 3
(BTW which one is a number:
23, 2.3,
2.3.4, 2.4e3, abc ?)
4 5
Is there a word in the file that is repeated 3 or more times?
6 7 8
Replaces all occurrences of Python or python by Java ... ... but avoid replacing Monty Python.
9 10 11
Given a text message fetch all the phone numbers:
Regular Expressions 12 13 14
Fetch numbers that look like 09-1234567 then also fetch +972-2-1234567 and maybe also 09-123-4567
15 16 17
Check if in a given text passing your network there are credit card numbers....
18 19 20
Given a text find if the word "password" is in it and fetch the surrounding text.
21 22 23
Given a log file like this:
24 25 26 27
[Tue Jun 12 00:01:00 2019] - (3423) - INFO - ERROR log restarted [Tue Jun 12 09:08:17 2019] - (3423) - INFO - System starts to work [Tue Jun 13 08:07:16 2019] - (3423) - ERROR - Something is wrong
28 29 30
provide statistics on how many of the different levels of log messages were seen. Separate the log messages into files.
Where can I use it ? • • • • • • • • • • • • •
grep, egrep Unix tools such as sed, awk, procmail vi, emacs, other editors text editors such as Multi-Edit .NET languages: C#, C++, VB.NET Java Perl Python PHP Ruby … Word, Open Office … PCRE
grep
263
264
Regular Expressions
grep gets a regex and one or more files. It goes over line-by-line all the files and displays the lines where the regex matched. A few examples:
1 2 3 4 5 6
grep python file.xml grep [34] file.xml grep [34] *.xml grep [0-9] *.xml egrep '\b[0-9]' *.xml r.
# # # # #
lines that have the string python lines that have either 3 or 4 (or lines that have either 3 or 4 (or lines with a digit in them. only highlight digits that are at
in them in file.xml. both) in file.xml. both) in every xml file. the beginning of a numbe\
Regexes first match 1
import re
2 3 4 5 6 7
text = 'The black cat climed' match = re.search(r'lac', text) if match: print("Matching") # Matching print(match.group(0)) # lac
8 9 10 11 12 13 14
match = re.search(r'dog', text) if match: print("Matching") else: print("Did NOT match") print(match) # None
The search method returns an object or None, if it could not find any match. If there is a match you can call the group() method. Passing 0 to it will return the actual substring that was matched.
Match numbers
Regular Expressions 1
import re
2 3
line = 'There is a phone number 12345 in this row and an age: 23'
4 5 6 7
match = re.search(r'\d+', line) if match: print(match.group(0)) # 12345
Use raw strings for regular expression: r’a\d’. Especially because \ needs it. • \d matches a digit. • + is a quantifier and it tells \d to match one or more digits. It matches the first occurrence. Here we can see that the group(0) call is much more interesting than earlier.
Capture 1
import re
2 3
line = 'There is a phone number 12345 in this row and an age: 23'
4 5 6 7
match = re.search(r'age: \d+', line) if match: print(match.group(0)) # age: 23
8 9 10 11 12 13
match = re.search(r'age: (\d+)', line) if match: print(match.group(0)) # age: 23 print(match.group(1)) # 23 the first group of parentheses
14 15 16
print(match.groups()) # ('23',) print(len(match.groups())) # 1
Parentheses in the regular expression can enclose any sub-expression. Whatever this sub-expression matches will be saved and can be accessed using the group() method.
Capture more
265
266
Regular Expressions 1
import re
2 3
line = 'There is a phone number 12345 in this row and an age: 23'
4 5 6 7 8 9
match = re.search(r'(\w+): if match: print(match.group(0)) print(match.group(1)) print(match.group(2))
(\d+)', line) # age: 23 # age the first group of parentheses # 23 the second group of parentheses
10 11 12 13
# print(match.group(3)) # IndexError: no such group print(match.groups()) # ('age', '23') print(len(match.groups())) # 2
Some groups might match ‘’ or even not match at all, in which case we get None in the appropriate match.group() call and in the match.groups() call
Capture even more 1
import re
2 3
line = 'There is a phone number 12345 in this row and an age: 23'
4 5 6 7 8 9 10
match = re.search(r'((\w+): (\d+))', line) if match: print(match.group(0)) # age: 23 print(match.group(1)) # age: 23 print(match.group(2)) # age print(match.group(3)) # 23
11 12 13
print(match.groups()) # ('age: 23', 'age', '23') print(len(match.groups())) # 3
findall
Regular Expressions 1
import re
2 3 4 5
line1 = 'There is a phone number 12345 in this row and another 42 number' numbers1 = re.findall(r'\d+', line1) print(numbers1) # ['12345', '42']
6 7 8 9
line2 = 'There are no numbers in this row. Not even one.' numbers2 = re.findall(r'\d+', line2) print(numbers2) # []
re.findall returns the matched substrings.
findall with capture 1
import re
2 3 4 5 6
line = 'There is a phone number 12345 in this row and another 42 number' match = re.search(r'\w+ \d+', line) if match: print(match.group(0)) # number 12345
7 8 9 10 11
match = re.search(r'\w+ (\d+)', line) if match: print(match.group(0)) # number 12345 print(match.group(1)) # 12345
12 13 14
matches = re.findall(r'\w+ \d+', line) print(matches) # ['number 12345', 'another 42']
15 16 17
matches = re.findall(r'\w+ (\d+)', line) print(matches) # ['12345', '42']
findall with capture more than one
267
Regular Expressions 1
import re
2 3 4 5 6 7
line = 'There is a phone number 12345 in this row and another 42 number' match = re.search(r'(\w+) (\d+)', line) if match: print(match.group(1)) # number print(match.group(2)) # 12345
8 9 10
matches = re.findall(r'(\w+) (\d+)', line) print(matches) # [('number', '12345'), ('another', '42')]
If there are multiple capture groups then The returned list will consist of tuples.
Any Character . matches any one character except newline. For example: #.# 1
import re
2 3 4 5 6 7 8 9 10 11 12 13 14 15
strings = [ 'abc', 'text: #q#', 'str: #a#', 'text #b# more text', '#a and this? #c#', '#a and this? # c#', '#@#', '#.#', '# #', '##' '###' ]
16 17 18 19 20 21
for s in strings: print('str: ', s) match = re.search(r'#.#', s) if match: print('match:', match.group(0))
268
269
Regular Expressions
If re.DOTALL is given newline will be also matched.
Match dot 1
import re
2 3 4 5 6 7 8
cases = [ "hello!", "hello world.", "hello. world", ".", ]
9 10 11 12 13 14
for case in cases: print(case) match = re.search(r'.', case) if match: print(match.group(0))
# Match any character
15 16
print("----")
17 18 19 20 21 22
for case in cases: print(case) match = re.search(r'\.', case) if match: print(match.group(0))
# Match a dot
23 24
print("----")
25 26 27 28 29 30
for case in cases: print(case) match = re.search(r'[.]', case) # Match a dot if match: print(match.group(0))
Character classes We would like to match any string that has any of the #a#, #b#, #c#, #d#, #e#, #f#, #@# or #.#
Regular Expressions 1
import re
2 3 4 5 6 7 8 9 10 11 12 13 14
strings = [ 'abc', 'text: #q#', 'str: #a#', 'text #b# more text', '#ab#', '#@#', '#.#', '# #', '##' '###' ]
15 16 17 18 19 20 21
1 2
for s in strings: print('str: ', s) match = re.search(r'#[abcdef@.]#', s) if match: print('match:', match.group(0)) r'#[abcdef@.]#' r'#[a-f@.]#'
Common characer classes • \d digit: [0-9] Use stand alone: \d or as part of a bigger character class: [abc\d] • \w word character: [0-9a-zA-Z_] • \s white space: [\f\t\n\r ] form-feed, tab, newline, carriage return and SPACE
Negated character class • • • •
[^abc] matches any one character that is not ‘a’, not ‘b’ and not ‘c’. D not digit [^\d] W not word character [^\w] S not white space [^\s]
Optional character Match the word color or the word colour
270
271
Regular Expressions 1
Regex: r'colou?r'
1
Input: color Input: colour Input: colouur
2 3
Regex 0 or more quantifier Any line with two - -es with anything in between. 1 2 3 4 5 6
Regex: Input: Input: Input: Input: Input:
r'-.*-' "ab" "ab - cde" "ab - qqqrq -" "ab -- cde" "--"
Quantifiers Quantifiers apply to the thing in front of them 1 2 3 4 5 6
r'ax*a' r'ax+a' r'ax?a' r'ax{2,4}a' r'ax{3,}a' r'ax{17}a'
# aa, axa, axxa, axxxa, # axa, axxa, axxxa, # aa, axa # axxa, axxxa, # axxxa, #
* + ?
Quantifiers limit
010-1 n-m nn
... ... axxxxa axxxxa, ... axxxxxxxxxxxxxxxxxa
Regular Expressions 1
import re
2 3 4 5 6 7
strings = ( "axxxa", "axxxxa", "axxxxxa", )
8 9 10 11 12 13 14 15
for text in strings: match = re.search(r'ax{4}', text) if match: print("Match") print(match.group(0)) else: print("NOT Match")
Quantifiers on character classes 1
import re
2 3 4 5 6 7 8 9 10
strings = ( "-a-", "-b-", "-x-", "-aa-", "-ab-", "--", )
11 12 13 14 15 16
for line in strings: match = re.search(r'-[abc]-', line) if match: print(line) print('=========================')
17 18 19 20 21 22
for line in strings: match = re.search(r'-[abc]+-', line) if match: print(line) print('=========================')
23 24
for line in strings:
272
273
Regular Expressions 25 26 27
match = re.search(r'-[abc]*-', line) if match: print(line)
Greedy quantifiers 1
import re
2 3 4
match = re.search(r'xa*', 'xaaab') print(match.group(0))
5 6 7
match = re.search(r'xa*', 'xabxaab') print(match.group(0))
8 9 10
match = re.search(r'a*', print(match.group(0))
'xabxaab')
match = re.search(r'a*', print(match.group(0))
'aaaxabxaab')
11 12 13
They match ‘xaaa’, ‘xa’ and ‘’ respectively.
Minimal quantifiers 1
import re
2 3 4
match = re.search(r'a.*b', 'axbzb') print(match.group(0))
5 6 7
match = re.search(r'a.*?b', 'axbzb') print(match.group(0))
8 9 10 11
match = re.search(r'a.*b', 'axy121413413bq') print(match.group(0))
12 13 14
match = re.search(r'a.*?b', 'axyb121413413q') print(match.group(0))
Regular Expressions
Anchors • • • •
1
A matches the beginning of the string Z matches the end of the string ^ matches the beginning of the row (see also re.MULTILINE) $ matches the end of the row but will accept a trailing newline (see also re.MULTILINE)
import re
2 3 4 5 6 7
lines = [ "text with cat in the middle", "cat with dog", "dog with cat", ]
8 9 10 11
for line in lines: if re.search(r'cat', line): print(line)
12 13 14 15 16 17
print("---") for line in lines: if re.search(r'^cat', line): print(line)
18 19 20 21 22
print("---") for line in lines: if re.search(r'\Acat', line): print(line)
23 24 25 26 27
print("---") for line in lines: if re.search(r'cat$', line): print(line)
28 29 30 31 32
print("---") for line in lines: if re.search(r'cat\Z', line): print(line)
274
Regular Expressions 1 2 3 4 5 6 7 8 9 10 11
text with cat in the middle cat with dog dog with cat --cat with dog --cat with dog --dog with cat --dog with cat
Anchors on both end 1
import re
2 3 4 5 6 7
strings = [ "123", "hello 456 world", "hello world", ]
8 9 10 11
for line in strings: if re.search(r'\d+', line): print(line)
12 13
print('---')
14 15 16 17
for line in strings: if re.search(r'^\d+$', line): print(line)
18 19 20
print('---')
21 22 23 24
for line in strings: if re.search(r'\A\d+\Z', line): print(line)
275
Regular Expressions 1 2 3 4 5 6
123 hello 456 world --123 --123
Match ISBN numbers 1
1
import re
2 3 4 5 6 7 8 9 10 11 12 13 14
strings = [ '99921-58-10-7', '9971-5-0210-0', '960-425-059-0', '80-902734-1-6', '85-359-0277-5', '1-84356-028-3', '0-684-84328-5', '0-8044-2957-X', '0-85131-041-9', '0-943396-04-2', '0-9752298-0-X',
15 16 17 18 19 20 21 22 23 24
'0-975229-1-X', '0-9752298-10-X', '0-9752298-0-Y', '910975229-0-X', '-------------', '0000000000000', ] for isbn in strings: print(isbn)
25 26 27
if (re.search(r'^[\dX-]{13}$', isbn)): print("match 1")
28 29 30
if (re.search(r'^\d{1,5}-\d{1,7}-\d{1,5}-[\dX]$', isbn) and len(isbn) == 13): print("match 2")
276
Regular Expressions
Matching a section 1
import re
2 3
text = "This is with some sections with special characters"
4 5 6 7
m = re.search(r'', text) if m: print(m.group(0))
Matching a section - minimal 1
import re
2 3
text = "This is with some sections with special characters"
4 5 6 7
m = re.search(r'', text) if m: print(m.group(0))
Matching a section negated character class 1
import re
2 3
text = "This is with some sections with special characters"
4 5 6 7
m = re.search(r']*>', text) if m: print(m.group(0))
DOTALL S (single line) if re.DOTALL is given, . will match any character. Including newlines.
277
278
Regular Expressions 1
import re
2 3
line = 'Before content After'
4 5 6 7 8 9 10 11
text = ''' Before
content
After '''
12 13 14 15 16
if (re.search(r'.*', line)): print('line'); if (re.search(r'.*', text)): print('text');
17 18
print('-' * 10)
19 20 21 22 23
if (re.search(r'.*', line, re.DOTALL)): print('line'); if (re.search(r'.*', text, re.DOTALL)): print('text');
MULTILINE M if re.MULTILNE is given, ^ will match beginning of line and $ will match end of line 1
import re
2 3
line = 'Start
blabla End'
4 5 6 7 8 9 10 11
text = ''' prefix Start blabla End postfix '''
12 13 14
regex = r'^Start[\d\D]*End$' m = re.search(regex, line)
Regular Expressions 15 16
if (m): print('line')
17 18 19 20
m = re.search(regex, text) if (m): print('text')
21 22
print('-' * 10)
23 24 25 26
m = re.search(regex, line, re.MULTILINE) if (m): print('line')
27 28 29 30
m = re.search(regex, text, re.MULTILINE) if (m): print('text')
4
line ---------line text
1
re.MULTILINE | re.DOTALL
1 2 3
Two regex with logical or All the rows with either ‘apple pie’ or ‘banana pie’ in them. 1
import re
2 3 4 5 6 7
strings = [ 'apple pie', 'banana pie', 'apple' ]
8 9 10 11 12 13 14
for s in strings: #print(s) match1 = re.search(r'apple pie', s) match2 = re.search(r'banana pie', s) if match1 or match2: print('Matched in', s)
279
Regular Expressions
Alternatives Alternatives 1
import re
2 3 4 5 6 7
strings = [ 'apple pie', 'banana pie', 'apple' ]
8 9 10 11 12
for s in strings: match = re.search(r'apple pie|banana pie', s) if match: print('Matched in', s)
Grouping and Alternatives Move the common part in one place and limit the alternation to the part within the parentheses. 1
import re
2 3 4 5 6 7
strings = [ 'apple pie', 'banana pie', 'apple' ]
8 9 10 11 12
for s in strings: match = re.search(r'(apple|banana) pie', s) if match: print('Matched in', s)
Internal variables
280
Regular Expressions 1
import re
2 3 4 5 6 7
strings = [ 'banana', 'apple', 'infinite loop', ]
8 9 10 11 12 13
for s in strings: match = re.search(r'(.)\1', s) if match: print(match.group(0), 'matched in', s) print(match.group(1))
More internal variables 1
(.)(.)\2\1
2 3
(\d\d).*\1
4 5
(\d\d).*\1.*\1
6 7
(.{5}).*\1
Regex DNA • DNA is built from G, A, T, C • Let’s create a random DNA sequence • Then find the longest repeated sequence in it
1 2
import re import random
3 4 5 6 7
chars = ['G', 'A', 'T', 'C'] dna = '' for i in range(100): dna += random.choice(chars)
8 9 10
print(dna)
281
Regular Expressions 11 12
''' Generating regexes:
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
([GATC]{1}).*\1 ([GATC]{2}).*\1 ([GATC]{3}).*\1 ([GATC]{4}).*\1 ''' length = 1 result = '' while True: regex = r'([GATC]{' + str(length) + r'}).*\1' #print(regex) m = re.search(regex, dna) if m: result = m.group(1) length += 1 else: break
30 31 32
print(result) print(len(result))
Regex IGNORECASE 1
import re
2 3
s = 'Python'
4 5 6
if (re.search('python', s)): print('python matched')
7 8 9
if (re.search('python', s, re.IGNORECASE)): print('python matched with IGNORECASE')
Regex VERBOSE X
282
283
Regular Expressions 1
import re
2 3
email = "[email protected]"
4 5 6 7
m = re.search(r'\w[\w.-]*\@([\w-]+\.)+(com|net|org|uk|hu|il)', email) if (m): print('match')
8 9 10 11 12 13 14 15 16 17
m = re.search(r''' \w[\w.-]* # username \@ ([\w-]+\.)+ # domain (com|net|org|uk|hu|il) # gTLD ''', email, re.VERBOSE) if (m): print('match')
Substitution 1
import re
2 3
line = "abc123def"
4 5 6
print(re.sub(r'\d+', ' ', line)) # "abc def" print(line) # "abc123def"
7 8 9
print(re.sub(r'x', ' y', line)) print(line)
# "abc123def" # "abc123def"
10 11 12 13 14 15 16
print(re.sub(r'([a-z]+)(\d+)([a-z]+)', r'\3\2\1', line)) print(re.sub(r''' ([a-z]+) # letters (\d+) # digits ([a-z]+) # more letters ''', r'\3\2\1', line, flags=re.VERBOSE)) # "def123abc"
#
"def123abc"
17 18 19
print(re.sub(r'...', 'x', line)) print(re.sub(r'...', 'x', line, count=1))
# "xxx" # "x123def"
20 21 22
print(re.sub(r'(.)(.)', r'\2\1', line)) print(re.sub(r'(.)(.)', r'\2\1', line, count=2))
# "ba1c32edf" # "ba1c23def"
Regular Expressions
findall capture If there are parentheses in the regex, it will return tuples of the matches 1
import re
2 3 4
line = 'There is a phone number 83795 in this row and another 42 number' print(line)
5 6 7 8 9
search = re.search(r'(\d)(\d)', line) if search: print(search.group(1)) # 8 print(search.group(2)) # 3
10 11 12 13
matches = re.findall(r'(\d)(\d)', line) if matches: print(matches) # [('8', '3'), ('7', '9'), ('4', '2')]
14 15 16 17
matches = re.findall(r'(\d)\D*', line) if matches: print(matches) # [('8', '3', '7', '9', '5', '4', '2')]
18 19 20
matches = re.findall(r'(\d)\D*(\d?)', line) print(matches) # [('8', '3'), ('7', '9'), ('5', '4'), ('2', '')]
21 22 23
matches = re.findall(r'(\d).*?(\d)', line) print(matches) # [('8', '3'), ('7', '9'), ('5', '4')]
24 25 26
matches = re.findall(r'(\d+)\D+(\d+)', line) print(matches) # [('83795', '42')]
27 28 29
matches = re.findall(r'(\d+).*?(\d+)', line) print(matches) # [('83795', '42')]
30 31 32
matches = re.findall(r'\d', line) print(matches) # ['8', '3', '7', '9', '5', '4', '2']
Fixing dates In the input we get dates like this 2010-7-5 but we would like to make sure we have two digits for both days and months: 2010-07-05
284
285
Regular Expressions 1
import re
2 3 4
def fix_date(date): return re.sub(r'-(\d)\b', r'-0\1', date)
5 6 7 8 9 10 11 12
dates = { '2010-7-5' '2010-07-5' '2010-07-05' '2010-7-15' }
: : : :
'2010-07-05', '2010-07-05', '2010-07-05', '2010-07-15',
13 14 15
for original in sorted(dates.keys()): result = fix_date(original)
16 17
assert result == dates[original]
18 19 20 21 22
1 2 3
print(f" old: {original}") print(f" new: {result}") print(f" expected: {dates[original]}") print("")
old: 2010-07-05 new: 2010-07-05 expected: 2010-07-05
4 5 6 7
old: 2010-07-5 new: 2010-07-05 expected: 2010-07-05
8 9 10 11
old: 2010-7-15 new: 2010-07-15 expected: 2010-07-15
12 13 14 15
old: 2010-7-5 new: 2010-07-05 expected: 2010-07-05
Duplicate numbers
286
Regular Expressions 1
import re
2 3 4 5
text = "This is 1 string with 3 numbers: 34" new_text = re.sub(r'(\d+)', r'\1\1', text) print(new_text) # This is 11 string with 33 numbers: 3434
6 7 8
double_numbers = re.sub(r'(\d+)', lambda match: str(2 * int(match.group(0))), text) print(double_numbers) # This is 2 string with 6 numbers: 68
Remove spaces 1
line = "
ab cd
"
2 3 4
res = line.lstrip(" ") print(f"'{res}'")
# 'ab cd
res = line.rstrip(" ") print(f"'{res}'")
# '
res = line.strip(" ") print(f"'{res}'")
# 'ab cd'
'
5 6 7
ab cd'
8 9 10 11 12 13
res = line.replace(" ", "") print(f"'{res}'") # 'abcd'
Replace string in assembly code 1 2 3 4 5 6 7 8 9 10 11
mv A, R3 mv R2, B mv R1, R3 mv B1, R4 add A, R1 add B, R1 add R1, R2 add R3, R3 add R21, X add R12, Y mv X, R2
287
Regular Expressions 1 2
import sys import re
3 4 5
if len(sys.argv) != 2: exit(f"Usage: {sys.argv[0]} FILENAME")
6 7
filename = sys.argv[1]
8 9 10
with open(filename) as fh: code = fh.read()
11 12 13 14 15 16
# assuming there are code = re.sub(r'R1', code = re.sub(r'R3', code = re.sub(r'R2', code = re.sub(r'R4',
no R4 'R4', 'R1', 'R3', 'R2',
values then 4 substitutions will do code) code) code) code)
17 18
1 2
print(code)
import sys import re
3 4 5
if len(sys.argv) != 2: exit(f"Usage: {sys.argv[0]} FILENAME")
6 7
filename = sys.argv[1]
8 9 10
with open(filename) as fh: code = fh.read()
11 12 13 14 15 16 17 18
# or without any assumption and in one substitution: mapping = { 'R1' : 'R2', 'R2' : 'R3', 'R3' : 'R1', }
19 20
code = re.sub(r'\b(R[123])\b', lambda match: mapping[match.group(1)], code)
21 22
print(code)
Regular Expressions 1 2
import sys import re
3 4 5
if len(sys.argv) != 2: exit(f"Usage: {sys.argv[0]} FILENAME")
6 7
filename = sys.argv[1]
8 9 10
with open(filename) as fh: code = fh.read()
11 12 13 14 15 16 17 18 19 20
# or without any assumption and in one substitution: mapping = { 'R1' : 'R2', 'R2' : 'R3', 'R3' : 'R1', 'R12' : 'R21', 'R21' : 'R12', }
21 22
code = re.sub(r'\b(R1|R2|R3|R12)\b', lambda match: mapping[match.group(1)], code)
23 24
1 2
print(code)
import sys import re
3 4 5
if len(sys.argv) != 2: exit(f"Usage: {sys.argv[0]} FILENAME")
6 7
filename = sys.argv[1]
8 9 10
with open(filename) as fh: code = fh.read()
11 12 13 14 15 16 17
# or without any assumption and in one substitution: mapping = { 'R1' : 'R2', 'R2' : 'R3', 'R3' : 'R1',
288
Regular Expressions
'R12' : 'R21', 'R21' : 'R12',
18 19 20
289
}
21 22
regex = r'\b(' + '|'.join(mapping.keys()) + r')\b'
23 24
code = re.sub(regex, lambda match: mapping[match.group(1)], code)
25 26
print(code)
Full example of previous 1 2 3 4
import import import import
sys os time re
5 6 7
if len(sys.argv)
" abc " =>
"abc "
"abc"
because of the greediness
minimal match
306
Regular Expressions 1
print("\N{GREEK CAPITAL LETTER DELTA}")
2 3 4 5 6 7 8
print("\u05E9") print("\u05DC") print("\u05D5") print("\u05DD") print("\u262E") print("\u1F426")
# "bird"
9 10
print("\u05E9\u05DC\u05D5\u05DD \u262E")
3
Hello World! Szia Világ! ����! ����
1
import re
1 2
2 3
filename = "mixed.txt"
4 5 6 7 8 9
with open(filename) as fh: lines = fh.readlines() for line in lines: if re.search('\N{IN HEBREW}', line): print(line)
Anchors Other example 1
import re
2 3 4 5 6 7 8 9
strings = [ "123-XYZ-456", "a 123-XYZ-456 b", "a 123-XYZ-456", "123-XYZ-456 b", "123-XYZ-456\n", ]
10 11 12 13
regexes = [ r'\d{3}-\w+-\d{3}', r'^\d{3}-\w+-\d{3}',
Regular Expressions
r'\d{3}-\w+-\d{3}$', r'^\d{3}-\w+-\d{3}$', r'^\d{3}-\w+-\d{3}\Z', r'\A\d{3}-\w+-\d{3}\Z',
14 15 16 17 18
]
19 20 21 22 23 24 25 26
for r in regexes: print(r) for s in strings: #print(r, s) if (re.search(r, s)): print(' ', s) print('-' * 10)
307
PyCharm PyCharm Intro • • • •
IDE - Integrated Development Environment Introspection Running, Debugging Refactoring
PyCharm configurations • Change the Python Interpreter: • PyCharm / Preferences / Project: (name) / Project Interpreter • File / Settings / Project Interpreter
PyCharm Project • At the opening create a new project (directory + Python version) • File/New Project
PyCharm Files • New file on Mac: Click on the project on the left hand side / Right-Click / New / File; Windows, Linux: Alt-Insert • PyCharm Python console - see next slide
PyCharm - run code • • • •
Run/Run Set command line parameters Set environment variables Run/Debug (but set breakpoints before)
PyCharm Python console at the bottom left
PyCharm 1 2 3 4 5
2 + 3 x = 2 print(x) def f(x, y): return x+y
6 7
f(4, 5)
Refactoring example with PyCharm • Change variable name (in scope only)
1 2 3
def add(x, y): z = x + y return z
4 5 6 7
def multiply(x, y): z = x * y return z
8 9 10 11 12
x = 2 y = 3 z = add(x, y) print(z)
13 14 15
z = multiply(x, y) print(z)
• Extract method
309
Python standard modules Some Standard modules • • • • • •
sys¹⁰² - System specific os¹⁰³ - Operating System stat¹⁰⁴ - inode table shutil¹⁰⁵ - File Operations glob¹⁰⁶ - Unix style pathname expansion subprocess¹⁰⁷ - Processes
• • • • • •
argparse¹⁰⁸ - Command Line Arguments re¹⁰⁹ - Regexes math¹¹⁰ - Mathematics time¹¹¹ - timestamp and friends datetime¹¹² - time management random¹¹³ - Random numbers
sys
¹⁰²http://docs.python.org/library/sys.html ¹⁰³http://docs.python.org/library/os.html ¹⁰⁴http://docs.python.org/library/stat.html ¹⁰⁵http://docs.python.org/library/shutil.html ¹⁰⁶http://docs.python.org/library/glob.html ¹⁰⁷http://docs.python.org/library/subprocess.html ¹⁰⁸http://docs.python.org/library/argparse.html ¹⁰⁹http://docs.python.org/library/re.html ¹¹⁰http://docs.python.org/library/math.html ¹¹¹http://docs.python.org/library/time.html ¹¹²http://docs.python.org/library/datetime.html ¹¹³http://docs.python.org/library/random.html
311
Python standard modules 1
import sys,os
2 3 4
print(sys.argv) # the list of the values # on the command line sys.argv[0] is the name of the Python script
5 6
print(sys.executable)
# path to the python interpreter
7 8 9 10 11
# print(sys.path) # list of file-system path strings for searching for modules # hard-coded at compile time but can be changed via the PYTHONPATH # environment variable or during execution by modifying sys.path
12 13 14
print(sys.version_info) # sys.version_info(major=2, minor=7, micro=12, releaselevel='final', serial=0)
15 16
print(sys.version_info.major)
# 2 or 3
17 18
print(sys.platform)
# darwin
or
linux2
or
win32
19 20 21 22 23
print(os.uname()) # On Mac: # ('Darwin', 'air.local', '16.3.0', 'Darwin Kernel Version 16.3.0: Thu Nov 17 20:23:\ 58 PST 2016; root:xnu-3789.31.2~1/RELEASE_X86_64', 'x86_64')
24 25 26 27
1
# On Linux: # posix.uname_result(sysname='Linux', nodename='thinkpad', release='5.0.0-32-generic\ ', version='#34-Ubuntu SMP Wed Oct 2 02:06:48 UTC 2019', machine='x86_64')
['examples/sys/mysys.py']
2 3
/usr/bin/python
4 5 6 7 8 9 10
['/Users/gabor/work/training/python/examples/sys', '/Users/gabor/python/lib/python2.7/site-packages/crypto-1.1.0-py2.7.egg', ..., '/Users/gabor/python', '/Users/gabor/python/lib/python2.7/site-packages', ...]
Writing to standard error (stderr)
312
Python standard modules 1
import sys
2 3 4 5
print("on stdout (Standard Output)") print("on stderr (Standard Error)", file=sys.stderr) sys.stderr.write("in stderr again\n")
Redirection: 1 2 3
python stderr.py > out.txt 2> err.txt python stderr.py 2> /dev/null python stderr.py > out.txt 2>&1
Current directory (getcwd, pwd, chdir) 1
import os
2 3 4
this_dir = os.getcwd() print(this_dir)
5 6 7
# os.chdir('/path/to/some/dir') os.chdir('..')
OS dir (mkdir, makedirs, remove, rmdir) 1 2
os.mkdir(path_to_new_dir) os.makedirs(path_to_new_dir)
3 4 5
os.remove() os.unlink()
remove a file (the same)
6 7 8 9
os.rmdir() os.removedirs() shutil.rmtree()
single empty directory empty subdirectories as well rm -rf
python which OS are we running on (os, platform)
Python standard modules 1 2
import os import platform
3 4 5 6
print(os.name) print(platform.system()) print(platform.release())
7 8 9 10
# posix # Linux # 5.3.0-24-generic
Get process ID 1
import os
2 3 4
print(os.getpid()) print(os.getppid())
2
93518 92859
1
echo $$
1
OS path 1
import os
2 3 4 5
os.path.basename(path_to_thing) os.path.dirname(path_to_thing) os.path.abspath(path_to_file)
6 7 8
os.path.exists(path_to_file) os.path.isdir(path_to_thing)
9 10
os.path.expanduser('~')
Traverse directory tree - list directories recursively
313
314
Python standard modules 1 2
import os import sys
3 4 5
if len(sys.argv) != 2: exit("Usage: {} PATH_TO_DIRECTORY".format(sys.argv[0]))
6 7
root = sys.argv[1]
8 9 10 11 12
for dirname, dirs, files in os.walk(root): #print(dirname) # relative path (from cwd) to the directory being processed #print(dirs) # list of subdirectories in the currently processed directory #print(files) # list of files in the currently processed directory
13
for filename in files: print(os.path.join(dirname, filename))
14 15 16
# relative path to the "current" fi\
le
os.path.join 1
import os
2 3 4
path = os.path.join('home', 'foo', 'work') print(path) # home/foo/work
Directory listing 1 2
import os import sys
3 4 5
if len(sys.argv) != 2: exit("Usage: {} directory".format(sys.argv[0]))
6 7 8 9 10 11
path = sys.argv[1] files = os.listdir(path) for name in files: print(name) print(os.path.join(path, name))
expanduser - handle tilde ∼
Python standard modules 1
315
import os
2 3 4 5 6
print( print( print( print(
os.path.expanduser("~") ) os.path.expanduser("~/work") ) os.path.expanduser("~/other") ) os.path.expanduser("some/other/dir/no/expansion") )
Listing specific files using glob 1
import glob
2 3 4
files = glob.glob("*.py") print(files)
5 6 7
files = glob.glob("/usr/bin/*.sh") print(files)
External command with system 1
import os
2 3
command = 'ls -l'
4 5
os.system(command)
If you wanted to list the content of a directory in an os independent way you’d use os.listdir('.') or you could use the glob.glob("*.py") function to have a subset of files.
subprocess Run external command and capture the output
316
Python standard modules 1 2
import time import sys
3 4 5 6 7
1 2
for i in range(3): print("OUT {}".format(i)) print("ERR {}".format(i), file=sys.stderr) time.sleep(1)
import subprocess import sys
3 4
command = [sys.executable, 'slow.py']
5 6 7 8 9
proc = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE, )
10 11
out,err = proc.communicate()
# runs the code
12 13
# out and err are two strings
14 15
print('exit code:', proc.returncode)
16 17 18 19
print('out:') for line in out.decode('utf8').split('\n'): print(line)
20 21 22 23
print('err:') for line in err.decode('utf8').split('\n'): print(line)
In this example p is an instance of the subprocess.PIPE class. The command is executed when the object is created.
subprocess in the background
317
Python standard modules 1 2 3
import subprocess import sys import time
4 5 6 7 8 9
proc = subprocess.Popen([sys.executable, 'slow.py'], stdout = subprocess.PIPE, stderr = subprocess.PIPE, )
10 11 12 13
#out, err = proc.communicate() #print(out) #print(err)
# this is when the code starts executing
14 15 16 17 18 19 20 21 22 23 24
timeout = 6 while True: poll = proc.poll() print(poll) time.sleep(0.5) timeout -= 0.5 if timeout %s", (min_score,))
13 14
size = 2
15 16 17 18 19 20 21 22
while True: rows = cursor.fetchmany(size) if not rows: break print(len(rows)) for row in rows: print(row)
23 24 25
cursor.close() conn.close()
26 27 28
if __name__ == "__main__": main(40)
Select into dictionaries 1
import mysql.connector
2 3 4 5 6 7 8 9
def main(): conn = mysql.connector.connect( host = 'localhost', database = 'fb_db', user = 'foobar', password='no secret')
10 11
cursor = conn.cursor(dictionary=True)
393
MySQL 12
cursor.execute("SELECT * FROM person")
13 14 15
for row in cursor: print(row)
16 17 18
cursor.close() conn.close()
19 20 21
if __name__ == "__main__": main()
Insert data 1
import mysql.connector
2 3 4 5 6 7 8 9
def main(name, birthdate, score): conn = mysql.connector.connect( host = 'localhost', database = 'fb_db', user = 'foobar', password='no secret')
10 11 12 13 14
cursor = conn.cursor() cursor.execute( "INSERT INTO person (name, birthdate, score) VALUES (%s, %s, %s)", (name, birthdate, score))
15 16 17 18 19 20
if cursor.lastrowid: print('last insert id', cursor.lastrowid) else: print('last insert id not found') conn.commit()
21 22
conn.close()
23 24 25
if __name__ == "__main__": main('Monty Python', '1969-10-05', 100)
Update data
394
MySQL 1
import mysql.connector
2 3 4 5 6 7 8 9
def main(uid, score): conn = mysql.connector.connect( host = 'localhost', database = 'fb_db', user = 'foobar', password='no secret')
10 11 12 13 14
cursor = conn.cursor() cursor.execute("UPDATE person SET score=%s WHERE id=%s", (score, uid)) conn.commit()
15 16
conn.close()
17 18 19
if __name__ == "__main__": main(12, 32)
Delete data 1
import mysql.connector
2 3 4 5 6 7 8 9
def main(uid): conn = mysql.connector.connect( host = 'localhost', database = 'fb_db', user = 'foobar', password='no secret')
10 11 12 13
cursor = conn.cursor() cursor.execute("DELETE FROM person WHERE id=%s", (uid,)) conn.commit()
14 15
conn.close()
16 17 18
if __name__ == "__main__": main(11)
395
MySQL
396
Exercise MySQL 1. Create a user with a password manually. 2. Create a database manually. 3. Create a table manually for describing fleet of cars: id, license-plate, year-built, brand, owner. (Owner is the name of the owner) 4. Create a program that accepts values on the command line and insterts the data in the database 5. Create another program that lists all the cars. 6. Improve the selector program to accept command line paramter –minage N and –maxage N and show the cars within those age limits (N is a number of years e.g. 3) 7. Create program to delete a car. 8. Create program to change the owner of a car.
Exercise: MySQL Connection Instead of hard-coding the connection details in the script, let’s create an INI file that contains the connection information and use that. 1 2 3 4 5
[development] host = localhost database = fb_db user = foobar password = no secret
Solution: MySQL Connection 1 2
import configparser import mysql.connector
3 4
config_file = 'examples/mysql/connect.ini'
5 6 7 8 9 10 11
def read_config(section = 'development'): print(section) cp = configparser.ConfigParser() cp.read(config_file) if not cp.has_section(section): raise Exception("No configuration found for '{}'".format(section))
12 13 14
return cp[section]
MySQL 15 16 17 18 19 20 21 22 23 24 25 26
def main(): try: db = read_config() print(db['password']) print(db) conn = mysql.connector.connect(**db) except mysql.connector.Error as e: print("MySQL exception: ", e) return except Exception as e: print("Other exception", e); return
27 28 29 30
if conn.is_connected(): print("is connected") print("Connected:", conn)
31 32
conn.close()
33 34 35
if __name__ == "__main__": main()
397
PostgreSQL PostgreSQL install 1
$ sudo aptitude install postgresql
2 3 4 5 6
$ sudo -i -u postgres $ createuser --interactive Add "ubuntu" as superuser $ createdb testdb
(we need a username that matches our Linux username)
7 8 9
$ psql $ sudo -u postgres psql
10 11 12
$ psql testdb testdb=# CREATE TABLE people (id INTEGER PRIMARY KEY, name VARCHAR(100));
Python and Postgresql 1 2
$ sudo aptitude install python3-postgresql $ sudo aptitude install python3-psycopg2
PostgreSQL connect 1
import psycopg2
2 3 4 5 6 7 8
try: conn = psycopg2.connect("postgresql:///testdb") #conn = psycopg2.connect("dbname='testdb' user='ubuntu' host='localhost' passwor\ d='secret'") except Exception as e: print("I am unable to connect to the database: ", e)
INSERT
PostgreSQL 1
import psycopg2
2 3 4 5 6
try: conn = psycopg2.connect("postgresql:///testdb") except Exception as e: print("I am unable to connect to the database: ", e)
7 8
cur = conn.cursor()
9 10 11
uid = 1 name = 'Foo'
12 13 14 15 16 17
1 2
try: cur.execute("INSERT INTO people (id, name) VALUES (%s, %s)", (uid, name)) conn.commit() except Exception as e: print(e)
duplicate key value violates unique constraint "people_pkey" DETAIL: Key (id)=(1) already exists.
INSERT (from command line) 1 2
import psycopg2 import sys
3 4 5
if len(sys.argv) != 3: exit("Usage: {} ID NAME".format(sys.argv[0]))
6 7
uid, name = sys.argv[1:]
8 9 10 11 12 13
try: conn = psycopg2.connect("postgresql:///testdb") except Exception as e: print("I am unable to connect to the database: ", e)
14 15
cur = conn.cursor()
16 17 18
try: cur.execute("INSERT INTO people (id, name) VALUES (%s, %s)", (uid, name))
399
PostgreSQL 19 20 21
conn.commit() except Exception as e: print(e)
SELECT 1
import psycopg2
2 3 4 5 6
try: conn = psycopg2.connect("postgresql:///testdb") except Exception as e: print("I am unable to connect to the database: ", e)
7 8
cur = conn.cursor()
9 10 11 12 13 14 15
try: cur.execute("SELECT * from people") for r in cur.fetchall(): print(r) except Exception as e: print(e)
DELETE 1
import psycopg2
2 3 4 5 6
try: conn = psycopg2.connect("postgresql:///testdb") except Exception as e: print("I am unable to connect to the database: ", e)
7 8
cur = conn.cursor()
9 10 11 12 13 14
try: cur.execute("DELETE FROM people") conn.commit() except Exception as e: print(e)
15 16 17
try: cur.execute("SELECT * from people")
400
PostgreSQL 18 19 20 21
for r in cur.fetchall(): print(r) except Exception as e: print(e)
401
SQLAlchemy SQLAlchemy hierarchy • ORM • Table, Metadata, Reflection, DDL - standardized language • Engine - standardize low-level access (placeholders)
SQLAlchemy engine 1 2 3
engine = create_engine('sqlite:///test.db') # relative path engine = create_engine('sqlite:////full/path/to/test.db') # full path engine = create_engine('sqlite://') # in memory database
PostgreSQL 1 2
engine = create_engine('postgresql://user:password@hostname/dbname') engine = create_engine('postgresql+psycopg2://user:password@hostname/dbname')
MySQL 1 2
engine = create_engine("mysql://user:password@hostname/dbname", encoding='latin1') #\ defaults to utf-8
SQLAlchemy autocommit Unlike the underlying database engines, SQLAlchemy uses autocommit. That is, usually we don’t need to call commit(), but if we would like to have a transaction we need to start it using begin() and end it either with commit() or with rollback().
SQLAlchemy engine CREATE TABLE
403
SQLAlchemy 1 2
import os from sqlalchemy import create_engine
3 4 5 6
dbname = 'test.db' if os.path.exists(dbname): os.unlink(dbname)
7 8
engine = create_engine('sqlite:///' + dbname)
# Engine
9 10 11 12 13 14 15 16
engine.execute(''' CREATE TABLE person ( id INTEGER PRIMARY KEY, name VARCHAR(100) UNIQUE, balance INTEGER NOT NULL ); ''')
SQLAlchemy engine INSERT 1 2
import os from sqlalchemy import create_engine
3 4
dbname = 'test.db'
5 6
engine = create_engine('sqlite:///' + dbname)
7 8 9 10 11 12 13 14 15
engine.execute('INSERT INTO 'Joe', balance = 100) engine.execute('INSERT INTO 'Jane', balance = 100) engine.execute('INSERT INTO 'Melinda', balance = 100) engine.execute('INSERT INTO 'George', balance = 100)
person (name, balance) VALUES (:name, :balance)', name =\ person (name, balance) VALUES (:name, :balance)', name =\ person (name, balance) VALUES (:name, :balance)', name =\ person (name, balance) VALUES (:name, :balance)', name =\
SQLAlchemy engine SELECT
404
SQLAlchemy 1
from sqlalchemy import create_engine
2 3
dbname = 'test.db'
4 5 6
engine = create_engine('sqlite:///' + dbname) result = engine.execute('SELECT * FROM person WHERE id=:id', id=3)
7 8 9
print(result) a0>
# help ... > show dbs admin (empty) demo 0.078GB local 0.078GB
8 9 10
> use demo (name of db) switched to db demo
11 12 13 14
> show collections people system.indexes
15 16 17 18 19 20 21 22 23 24 25
> db.people.find() { "_id" : ObjectId("58a3e9b2962d747a9c6e676c"), "email" : "[email protected]", "studen\ t" : true, "birthdate" : ISODate("2002-01-02T00:00:00Z"), "name" : "Foo" } { "_id" : ObjectId("58a3e9b2962d747a9c6e676d"), "email" : "[email protected]", "name" \ : "Bar", "student" : true, "birthdate" : ISODate("1998-08-03T00:00:00Z"), "teacher" : false } { "_id" : ObjectId("58a3e9b2962d747a9c6e676e"), "email" : "[email protected]", "birthdate" : ISODate("1995-12-12T00:00:00Z"), "teacher" : true, "name" : "Zorg"\ }
26 27 28
> db.people.drop() > db.dropDatabase()
(drop a collection) (drop a whole database)
Python MongoDB find 1 2
from pymongo import MongoClient import datetime
3 4 5
client = MongoClient() db = client.demo
6 7 8
for person in db.people.find(): print(person)
Python MongoDB find refine
MongoDB 1 2
from pymongo import MongoClient import datetime
3 4 5
client = MongoClient() db = client.demo
6 7 8
for person in db.people.find({ 'name' : 'Foo'}): print(person)
Python MongoDB update 1 2
from pymongo import MongoClient import datetime
3 4 5
client = MongoClient() db = client.demo
6 7 8 9
db.people.update({ 'name' : 'Zorg'}, { '$set' : { 'salary' : 1000 } }) for p in db.people.find({ 'name' : 'Zorg'}): print(p)
Python MongoDB remove (delete) 1 2
from pymongo import MongoClient import datetime
3 4 5
client = MongoClient() db = client.demo
6 7 8 9
db.people.remove({ 'name' : 'Zorg'}) for p in db.people.find(): print(p)
Python MongoDB replace
426
MongoDB 1 2
from pymongo import MongoClient import datetime
3 4 5
client = MongoClient() collection = client.demo.cache
6 7 8 9 10
data1 = { 'total': 10, 'current': 5, }
11 12 13 14 15
data2 = { 'total': 13, 'current': 3, }
16 17 18 19 20 21 22
def show(): print(collection.count_documents({})) for entry in collection.find({}): print(entry) print()
23 24 25
collection.drop() print(collection.count_documents({}))
26 27 28
collection.insert_one({ '_id' : 'stats', **data1}) show()
29 30 31
1 2 3
collection.replace_one({ '_id' : 'stats'}, data2) show()
0 1 {'_id': 'stats', 'total': 10, 'current': 5}
4 5 6
1 {'_id': 'stats', 'total': 13, 'current': 3}
Python MongoDB upsert
427
MongoDB 1 2
from pymongo import MongoClient import datetime
3 4 5
client = MongoClient() collection = client.demo.cache
6 7 8 9 10
data1 = { 'total': 10, 'current': 5, }
11 12 13 14 15
data2 = { 'total': 13, 'current': 3, }
16 17 18 19 20 21 22
def show(): print(collection.count_documents({})) for entry in collection.find({}): print(entry) print()
23 24 25
collection.drop() print(collection.count_documents({}))
26 27 28
collection.update_one({ '_id' : 'stats'}, { '$set': data1 }, upsert=True) show()
29 30 31 1 2 3
collection.update_one({ '_id' : 'stats'}, { '$set': data2 }, upsert=True) show() 0 1 {'_id': 'stats', 'current': 5, 'total': 10}
4 5 6
1 {'_id': 'stats', 'current': 3, 'total': 13}
Python Mongodb: TypeError: upsert must be True or False
428
MongoDB 1 2
429
from pymongo import MongoClient import datetime
3 4 5
import pymongo print(pymongo.__version__)
6 7 8
client = MongoClient() collection = client.demo.data
9 10 11 12 13
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
collection.drop() collection.update_one({ '_id' : 'stats'}, { '$set': { 'total': 1 } }, upsert=True) collection.update_one({ '_id' : 'stats'}, { '$set': { 'total': 2 } }, { "upsert": Tr\ ue })
3.10.1 Traceback (most recent call last): File "examples/mongodb/upsert_error.py", line 12, in collection.update_one({ '_id' : 'stats'}, { '$set': { 'total': 2 } }, { "upsert"\ : True }) File "/home/gabor/venv3/lib/python3.8/site-packages/pymongo/collection.py", line 9\ 98, in update_one self._update_retryable( File "/home/gabor/venv3/lib/python3.8/site-packages/pymongo/collection.py", line 8\ 54, in _update_retryable return self.__database.client._retryable_write( File "/home/gabor/venv3/lib/python3.8/site-packages/pymongo/mongo_client.py", line\ 1491, in _retryable_write return self._retry_with_session(retryable, func, s, None) File "/home/gabor/venv3/lib/python3.8/site-packages/pymongo/mongo_client.py", line\ 1384, in _retry_with_session return func(session, sock_info, retryable) File "/home/gabor/venv3/lib/python3.8/site-packages/pymongo/collection.py", line 8\ 46, in _update return self._update( File "/home/gabor/venv3/lib/python3.8/site-packages/pymongo/collection.py", line 7\ 67, in _update common.validate_boolean("upsert", upsert) File "/home/gabor/venv3/lib/python3.8/site-packages/pymongo/common.py", line 159, \ in validate_boolean raise TypeError("%s must be True or False" % (option,)) TypeError: upsert must be True or False
Redis Redis CLI redis-cli¹²⁸ 1 2 3 4 5
$ > > > >
redis-cli set name foo get name set name "foo bar" get name
> > > >
set a 1 get a incr a get a
6 7 8 9 10 11 12 13 14
> set b 1 > keys * > del b
Redis list keys 1 2
import redis r = redis.StrictRedis()
3 4 5
for k in r.keys('*'): print(k)
Redis set get
¹²⁸https://redis.io/topics/rediscli
Redis 1 2
import redis r = redis.StrictRedis()
3 4 5
r.set("name", "some value") print(r.get("name"))
Redis incr 1 2
import redis r = redis.StrictRedis()
3 4 5 6 7 8
r.set("counter", 40) print(r.get("counter")) print(r.incr("counter")) print(r.incr("counter")) print(r.get("counter"))
Redis incrby 1 2
import redis r = redis.StrictRedis()
3 4 5 6 7
r.set("counter", 19) print(r.get("counter")) print(r.incrby("counter", 23)) print(r.get("counter"))
Redis setex Set with expiration time in seconds.
431
Redis 1 2 3
import redis import time r = redis.StrictRedis()
4 5 6 7 8 9 10 11
r.setex("login", 2, 'foobar') print(r.get("login")) # 'foobar' time.sleep(1) print(r.get("login")) # 'foobar' time.sleep(1) print(r.get("login")) # None
432
Web client urllib the web client 1
import urllib
2 3 4 5 6 7
# f is like a filehand for http requests, but it cannot be user "with" # Only works in Python 2 f = urllib.urlopen('http://python.org/') html = f.read() # is like a get() request f.close()
8 9
print(html)
10 11 12 13
# retrieve a file and save it locally: urllib.urlretrieve('http://www.python.org/images/python-logo.gif', 'logo.gif')
urllib2 the web client urllib2 is better than urllib as it will indicate if there was an error retreiving
1
import urllib2
2 3 4 5 6 7
# f is like a filehand for http requests f = urllib2.urlopen('http://python.org/') html = f.read() # is like a get() request f.close() print(html)
8 9 10 11 12
try: f = urllib2.urlopen('http://python.org/some_missing_page') html = f.read()
Web client 13 14 15 16
434
f.close() print(html) except urllib2.HTTPError as e: print(e) # HTTP Error 404: OK
httpbin.org • httpbin.org¹²⁹ • source¹³⁰
requests get 1
import requests
2 3 4 5 6 7
r = requests.get('http://httpbin.org/') print(type(r)) print(r.status_code) print(r.headers) print(r.headers['content-type'])
• HTTP status codes¹³¹ • Python requests¹³²
Download image using requests 1
import requests
2 3 4 5 6 7 8 9
url = 'https://bloximages.newyork1.vip.townnews.com/wpsdlocal6.com/content/tncms/ass\ ets/v3/editorial/7/22/722f8401-e134-5758-9f4b-a542ed88a101/5d41b45d92106.image.jpg' filename = "source.jpg" res = requests.get(url) print(res.status_code) with open(filename, 'wb') as fh: fh.write(res.content)
Download image as a stream using requests ¹²⁹http://httpbin.org ¹³⁰https://github.com/Runscope/httpbin ¹³¹https://en.wikipedia.org/wiki/List_of_HTTP_status_codes ¹³²http://docs.python-requests.org/
Web client 1 2
435
import requests import shutil
3 4 5 6 7 8 9 10 11
url = 'https://bloximages.newyork1.vip.townnews.com/wpsdlocal6.com/content/tncms/ass\ ets/v3/editorial/7/22/722f8401-e134-5758-9f4b-a542ed88a101/5d41b45d92106.image.jpg' filename = "source.jpg" res = requests.get(url, stream=True) print(res.status_code) with open(filename, 'wb') as fh: res.raw.decode_content shutil.copyfileobj(res.raw, fh)
Download zip file 1 2
import requests import shutil
3 4 5
url = "https://code-maven.com/public/developer_survey_2019.zip" filename = "developer_survey_2019.zip"
6 7 8 9 10 11 12
res = requests.get(url, stream=True) print(res.status_code) if res.status_code == 200: with open(filename, 'wb') as fh: res.raw.decode_content shutil.copyfileobj(res.raw, fh)
Extract zip file 1
import zipfile
2 3 4 5
path = "developer_survey_2019.zip" z = zipfile.ZipFile(path) z.extractall()
Interactive Requests
Web client 1
import requests
2 3
r = requests.get('http://httpbin.org/')
4 5 6
import code code.interact(local=locals())
requests get JSON 1
import requests
2 3 4 5 6 7 8
r = requests.get('http://httpbin.org/ip') print(r.headers['content-type']) print(r.text) data = r.json() print(data) print(data['origin'])
requests get JSON UserAgent 1
import requests
2 3 4 5 6 7 8
r = requests.get('http://httpbin.org/user-agent') print(r.headers['content-type']) print(r.text) data = r.json() print(data) print(data['user-agent'])
requests get JSON UserAgent
436
Web client 1
import requests
2 3 4 5 6 7 8 9
r = requests.get('http://httpbin.org/user-agent', headers = {'User-agent': 'Internet Explorer/2.0'}) print(r.headers['content-type']) print(r.text) data = r.json() print(data) print(data['user-agent'])
requests get header 1
import requests
2 3 4
r = requests.get('http://httpbin.org/headers') print(r.text)
5 6 7 8 9 10 11 12 13
# { # "headers": { # "Accept": "*/*", # "Accept-Encoding": "gzip, deflate", # "Host": "httpbin.org", # "User-Agent": "python-requests/2.3.0 CPython/2.7.12 Darwin/16.3.0" # } # }
requests change header 1
import requests
2 3 4 5 6 7 8 9 10
r = requests.get('http://httpbin.org/headers', headers = { 'User-agent' : 'Internet Explorer/2.0', 'SOAPAction' : 'http://www.corp.net/some/path/CustMsagDown.Check', 'Content-type': 'text/xml' } ) print(r.text)
11 12 13
# { # "headers": {
437
Web client 14 15 16 17 18 19 20 21
# # # # # # # } # }
438
"Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Type": "text/xml", "Host": "httpbin.org", "Soapaction": "http://www.corp.net/some/path/CustMsagDown.Check", "User-Agent": "Internet Explorer/2.0"
requests post 1
import requests
2 3 4 5 6 7 8 9 10 11 12 13 14
payload = '''
327
'''
15 16 17 18 19 20 21 22 23 24 25
r = requests.post('http://httpbin.org/post', headers = { 'User-agent' : 'Internet Explorer/2.0', 'SOAPAction' : 'http://www.corp.net/some/path/CustMsagDown.Check', 'Content-type': 'text/xml' }, data = payload, ) print(r.headers['content-type']) print(r.text)
Tweet
Web client 1 2 3
439
import configparser import twitter import os
4 5 6 7
config = configparser.ConfigParser() config.read(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'api.cfg')); api = twitter.Api( **config['twitter'] )
8 9 10
status = api.PostUpdate('My first Tweet using Python') print(status.text)
API config file 1 2 3 4 5
[twitter] consumer_key= consumer_secret= access_token_key= access_token_secret=
6 7 8
[bitly] access_token=
bit.ly 1 2 3
import configparser import os import requests
4 5 6 7 8
def shorten(uri): config = configparser.ConfigParser() #config.read(os.path.join(os.path.expanduser('~'), 'api.cfg')) config.read(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'api.cfg'))
9 10 11 12 13
query_params = { 'access_token': bitly_config['bitly']['access_token'], 'longUrl': uri }
14 15 16 17
endpoint = 'https://api-ssl.bitly.com/v3/shorten' response = requests.get(endpoint, params=query_params, verify=False)
Web client 18
440
data = response.json()
19 20 21 22 23
if not data['status_code'] == 200: exit("Unexpected status_code: {} in bitly response. {}".format(data['status_\ code'], response.text)) return data['data']['url']
24 25
print(shorten("http://code-maven.com/"))
Exercise: Combine web server and client Write a web application that can get a site and a text as input (e.g. http://cnn.com and ‘Korea’) check if on the given site the word appears or not? Extended version: Only get the URL as the input and create statistics, which are the most frequent words on the given page.
Python Web server Hello world web 1 2
from wsgiref.util import setup_testing_defaults from wsgiref.simple_server import make_server
3 4
import time
5 6 7
def hello_world(environ, start_response): setup_testing_defaults(environ)
8 9 10
status = '200 OK' headers = [('Content-type', 'text/plain')]
11 12
start_response(status, headers)
13 14
return "Hello World " + str(time.time())
15 16 17 18 19
port = 8080 httpd = make_server('0.0.0.0', port, hello_world) print("Serving on port {}...".format(port)) httpd.serve_forever()
Dump web environment info 1 2
from wsgiref.util import setup_testing_defaults from wsgiref.simple_server import make_server
3 4 5 6 7
# A relatively simple WSGI application. It's going to print out the # environment dictionary after being updated by setup_testing_defaults def simple_app(environ, start_response): setup_testing_defaults(environ)
8 9 10 11
status = '200 OK' headers = [('Content-type', 'text/plain')]
Python Web server 12
start_response(status, headers)
13 14 15 16
ret = ["{}: {}\n".format(key, value) for key, value in environ.iteritems()] return ret
17 18 19 20
httpd = make_server('', 8000, simple_app) print("Serving on port 8000...") httpd.serve_forever()
21 22
# taken from the standard documentation of Python
Web echo 1 2
from wsgiref.util import setup_testing_defaults from wsgiref.simple_server import make_server
3 4 5
import time import cgi
6 7 8
def hello_world(environ, start_response): setup_testing_defaults(environ)
9 10 11
status = '200 OK' headers = [('Content-type', 'text/html')]
12 13
start_response(status, headers)
14 15 16 17
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ) if 'txt' in form: return 'Echo: ' + form['txt'].value
18 19 20 21 22 23 24 25 26 27
return """
""" httpd = make_server('', 8000, hello_world) print("Serving on port 8000...") httpd.serve_forever()
442
Python Web server
Web form 1 2
from wsgiref.util import setup_testing_defaults from wsgiref.simple_server import make_server
3 4 5
import time import cgi
6 7 8
def hello_world(environ, start_response): setup_testing_defaults(environ)
9 10 11
status = '200 OK' headers = [('Content-type', 'text/html')]
12 13
start_response(status, headers)
14 15 16 17 18
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ) html = '' for f in form: html += f + '==' + form[f].value + '
'
19 20 21 22 23 24 25 26 27 28 29 30 31 32
if not html: html = """ click
Username:
Password:
Age group: Under 18 18-30 30-
""" return html
33 34 35 36
httpd = make_server('', 8000, hello_world) print("Serving on port 8000...") httpd.serve_forever()
443
Python Web server
Resources • wsgi tutorial¹³³ ¹³³http://archimedeanco.com/wsgi-tutorial/
444
Python Flask Python Flask intro Flask is a light-weight web micro-framework in Python. By default it uses a templating system called Jinja and a WSGI web application library called Werkzeug. In Flask you map URL paths to functions so when someone reaches the endpoint defined by the path the specific function is executed. The function is expected to return the HTML to be displayed. It is very easy to get started with Flask both if you’d like to build a web-site with HTML pages or if you are interested in providing an API that returns JSON.
• Flask¹³⁴ • Jinja¹³⁵ • Werkzeug¹³⁶
Python Flask installation 1 2
virtualenv venv -p python3 source venv/bin/activate
3 4
pip install flask
Flask: Hello World The de-facto standard first thing to do in programming in every language or framework is to print “Hello World” on the screen. This is what we are going to do with Flask now. This is probably the most simple Flask application. For this we need to create regular Python file, for example app.py. I’d recommend you first create a new empty directory and ¹³⁴https://flask.palletsprojects.com/ ¹³⁵https://jinja.palletsprojects.com/ ¹³⁶https://werkzeug.palletsprojects.com/
Python Flask
put the file inside that directory. The first thing is to load the Flask class from the flask module. Then we create an object representing the whole application. You could use any variable name for this, but the “standard” is to use the name app. Then comes the interesting part. We declare a function that will return the HTML page. In our example the name of the function is main, but the name actually is not important. You could as well call it some_other_name. The important part is the decorator above it. That decorator means that if someone reaches the path / on the web site, this function will be executed and whatever it returns will be sent back to the browser. This mapping of a path to a function is called URL routing and we’ll discuss it in detail later on. For now, let’s see how we can use this.
1
from flask import Flask
2 3
app = Flask(__name__)
4 5 6 7
@app.route("/") def main(): return "Hello World!"
Flask: Run Hello World In order to run this we need to set the environment variable FLASK_APP to the name of the file without the extension. We can also set the FLASK_DEBUG environment variable to 1 tuning on the debug-mode, but this is not required for this example. Then we execute flask run. It is a bit different how you do this on Linux or Mac vs. on MS Windows. In either case once flask is running you can use your browser to visit your new web application on http://127.0.0.1:5000/ You can also use curl on the command line to see the content of the web page. Once you have enough, you can hit Ctr-C to stop the program.
446
Python Flask
Linux/Mac: 1
FLASK_APP=app FLASK_DEBUG=1 flask run
2 3 4
Visit: http://127.0.0.1:5000/ curl http://localhost:5000/
Windows on the command line or in the terminal of Pycharm: 1 2 3
set FLASK_APP=app set FLASK_DEBUG=1 flask run
• To stop it use Ctrl-C
Flask: testing hello world Before we go ahead learning how to create more complex web applications we need to learn another very important feature of Flask. Flask makes it very easy to test your web application without even running a web server. For this we created a file called test_app.py in the same folder as we have the app.py with the following content. The name of the files must start with the word test_, but otherwise you can pick any filename. Inside we import the application and we have a test function, again its name must start with test_. From the app we can get the test_client which is a representation of our running web application. Then we can send in various requests. In this case we sent in an HTTP GET request to the root of the site. We get back a response object that we can then interrogate with various assertions. To run this we’ll need to install pytest and then we can just type in pytest. It will find and run the tests.
447
Python Flask 1
import app
2 3 4
def test_app(): web = app.app.test_client()
5 6 7 8
1
rv = web.get('/') assert rv.status == '200 OK' assert rv.data == b'Hello World!'
pytest
Flask generated page - time Showing a static text in the previous example was already a success, but we would like to be able to have a more dynamic web site. In this example we’ll see how to display the current time. We have the same skeleton as in the previous example, but this time the main function serving the root path returns some HTML that will be displayed as a link to the /time path. We also have a second route mapping the /time path to the show_time function. We run the application the same way as before on the command line. Now if we access the http://127.0.0.1:5000/ URL we’ll see the text time that we can click on. When we click on it we arrive at the http://127.0.0.1:5000/time page that shows the current time. Actually it will show the number of seconds from the epoch, which is January 1, 1970, 00:00:00 (UTC). Something like this: 1594528012.7892551
448
Python Flask 1 2
from flask import Flask import time
3 4
app = Flask(__name__)
5 6 7 8
@app.route("/") def main(): return 'time'
9 10 11 12
1
@app.route("/time") def show_time(): return str(time.time())
FLASK_APP=app FLASK_DEBUG=1 flask run
Flask generated page - time tested How can we test the version of our application that also has a generated page? We need to test two pages. There are many ways to divide our tests. • We could put all the tests in a single test-function. • We could have two test-functions in the same test-file. • We could have two test-functions in two separate test-files. Putting them in separate functions allows us to run them separately. It also means that if one fails the other might still pass. Usually we put independent test-cases in separate functions. Because it is still so small, putting them in two separate files seems to be an overkill. The test_home function is relatively straight forward. We get the main page and then we check the status-code and the exact match for the content. The test_time function is trickier. We can’t check an exact match as the timestamp will be different every time we run the code. We could mock the time, but we are looking for a simpler solution. So instead of an exact match we use a regexp to check if the result looks like a number we would expect. You can run the tests by running pytest.
449
Python Flask 1 2
import app import re
3 4 5
def test_home(): web = app.app.test_client()
6 7 8 9
rv = web.get('/') assert rv.status == '200 OK' assert rv.data == b'time'
10 11 12
def test_time(): web = app.app.test_client()
13 14 15 16
1
rv = web.get('/time') assert rv.status == '200 OK' assert re.search(r'\d+\.\d+$', rv.data.decode('utf-8'))
pytest
Flask: Echo GET 1 2
from flask import Flask, request app = Flask(__name__)
3 4 5 6 7 8 9 10 11
@app.route("/") def main(): return '''
'''
12 13 14 15
@app.route("/echo") def echo(): return "You said: " + request.args.get('text', '')
450
Python Flask 1
import app
2 3 4
def test_app(): web = app.app.test_client()
5 6 7 8
rv = web.get('/') assert rv.status == '200 OK' assert '' in rv.data.decode('utf-8')
9 10 11 12
rv = web.get('/echo') assert rv.status == '200 OK' assert b"You said: " == rv.data
13 14 15 16
rv = web.get('/echo?text=foo+bar') assert rv.status == '200 OK' assert b"You said: foo bar" == rv.data
2
curl http://localhost:5000/ curl http://localhost:5000/echo?text=Sanch+Panza
1
import requests
1
2 3 4 5
res = requests.get('http://localhost:5000/') print(res.status_code) print(res.text)
6 7 8 9
res = requests.get('http://localhost:5000/echo?text=Hello World!') print(res.status_code) print(res.text)
Flask: Echo POST
451
Python Flask 1
from flask import Flask, request
2 3
app = Flask(__name__)
4 5 6 7 8 9 10 11 12
@app.route("/") def main(): return '''
'''
13 14 15 16 17 18 19 1
@app.route("/echo", methods=['POST']) def echo(): if 'text' in request.form: return "You said: " + request.form['text'] else: return "Nothing to say?" import app
2 3 4
def test_app(): web = app.app.test_client()
5 6 7 8
rv = web.get('/') assert rv.status == '200 OK' assert '' in rv.data.decode('utf-8')
9 10 11 12 13
rv = web.get('/echo') assert rv.status == '405 METHOD NOT ALLOWED' assert '405 Method Not Allowed' in rv.data.decode('utf-8')
14 15 16 17 18
rv = web.post('/echo') assert rv.status == '200 OK' assert b"Nothing to say?" == rv.data
19 20 21 22 23
rv = web.post('/echo', data={ "text": "foo bar" }) assert rv.status == '200 OK' assert b"You said: foo bar" == rv.data
452
Python Flask 1
curl --data "text=Sancho Panza" http://localhost:5000/echo
1
import requests
2 3 4 5
res = requests.get('http://localhost:5000/') print(res.status_code) print(res.text)
6 7 8 9 10
res = requests.post('http://localhost:5000/echo', data={"text": "Hello World!"}) print(res.status_code) print(res.text)
Flask: templates 1 2
from flask import Flask, request app = Flask(__name__)
3 4 5 6
@app.route("/") def main(): return render_template('index.html')
7 8 9 10
@app.route("/echo", methods=['POST']) def echo(): return "You said: " + request.form['text']
4
1
FLASK_APP=echo_post FLASK_DEBUG=0 flask run
1 2 3
Internal Server Error 1
FLASK_APP=echo_post FLASK_DEBUG=1 flask run
Flask: templates
453
Python Flask 1 2
from flask import Flask, request, render_template app = Flask(__name__)
3 4 5 6
@app.route("/") def main(): return render_template('index.html')
7 8 9 10
@app.route("/echo", methods=['POST']) def echo(): return "You said: " + request.form['text']
Flask: templates with parameters 1 2
from flask import Flask, request, render_template app = Flask(__name__)
3 4 5 6
@app.route("/") def main(): return render_template('echo.html')
7 8 9 10
1 2 3 4
@app.route("/echo", methods=['POST']) def echo(): return render_template('echo.html', text=request.form['text'])
5 6 7 8
{% if text %} You said: {{ text }} {% endif %}
454
455
Python Flask 1
import echo
2 3 4
def test_app(): web = echo.app.test_client()
5
rv = web.get('/') assert rv.status == '200 OK' assert '' in rv.data.decode('utf-8')
6 7 8 9
rv = web.post('/echo', data={ "text": "foo bar" }) assert rv.status == '200 OK' assert "You said: foo bar" in rv.data.decode('utf-8')
10 11 12
Flask: runner 1
$ cd examples/flask/params
1
$ export FLASK_APP=echo $ export FLASK_DEBUG=1 $ flask run
2 3
or 1
$ FLASK_APP=echo.py FLASK_DEBUG=1
flask run
on windows 1 2 3
> set FLASK_APP=echo > set FLASK_DEBUG=1 > flask run
Other parameters 1
$ FLASK_APP=echo.py FLASK_DEBUG=1
flask run --port 8080 --host 0.0.0.0
Exercise: Flask calculator Write a web application that has two entry boxes and a button and that will add the two numbers inserted into the entry boxes.
Static files
Python Flask 1 2
from flask import Flask, request, render_template, url_for app = Flask(__name__)
3 4 5 6
@app.route("/") def main(): return render_template('main.html')
7 8 9 10 11
1 2 3 4
1 2 3 4 5 6
1 2 3 4 5 6 7 8
@app.route("/other") def other(): return render_template('other.html', img_path = url_for('static', filename='img/python.png'))
Main page
other
Other page img_path: {{ img_path }}
main
. ├── ├── │ │ └──
app.py static └── img └── python.png templates ├── main.html └── other.html
Flask Logging
456
Python Flask 1 2
457
from flask import Flask app = Flask(__name__)
3 4 5 6 7 8 9
@app.route("/") def main(): app.logger.debug("Some debug message") app.logger.warning("Some warning message") app.logger.error("Some error message") return "Hello World"
Flask: Counter 1 2
from flask import Flask app = Flask(__name__)
3 4
counter = 1
5 6 7 8 9 10
@app.route("/") def main(): global counter counter += 1 return str(counter)
Access the page from several browsers. There is one single counter that lives as long as the process lives.
Color selector without session 1 2 3
from flask import Flask, request, render_template import re app = Flask(__name__)
4 5 6 7 8 9 10
@app.route("/",methods=['GET', 'POST'] ) def main(): color = "FFFFFF" new_color = request.form.get('color', '') if re.search(r'^[0-9A-F]{6}$', new_color): color = new_color
11 12
return render_template('main.html', color = color)
Python Flask 1 2 3 4 5
6 7 8 9 10 11 12
home
Session management 1 2 3 4
from flask import Flask, request, render_template, session import re app = Flask(__name__) app.secret_key = 'blabla'
5 6 7 8 9
@app.route("/",methods=['GET', 'POST'] ) def main(): color = session.get('color', 'FFFFFF') app.logger.debug("Color: " + color)
10 11 12 13 14 15
new_color = request.form.get('color', '') if re.search(r'^[0-9A-F]{6}$', new_color): app.logger.debug('New color: ' + new_color) session['color'] = new_color color = new_color
16 17
return render_template('main.html', color = color)
Flask custom 404 page
458
Python Flask 1 2
from flask import Flask app = Flask(__name__)
3 4 5 6 7 8 9
1 2
@app.route("/") def main(): return ''' Main 404 page '''
from flask import Flask app = Flask(__name__)
3 4 5 6 7 8 9
@app.route("/") def main(): return ''' Main 404 page '''
10 11 12 13
1
@app.errorhandler(404) def not_found(e): return "Our Page not found", 404
curl -I http://localhost:5000/not
2 3
HTTP/1.0 404 NOT FOUND
Flask Error page 1 2
from flask import Flask app = Flask(__name__)
3 4 5 6 7 8 9 10
@app.route("/") def main(): return ''' Main bad '''
459
460
Python Flask 11 12 13 14
@app.route("/bad") def bad(): raise Exception("This is a bad page") return 'Bad page'
Will not trigger in debug mode! 1
$ FLASK_APP=echo.py FLASK_DEBUG=0
1
curl -I http://localhost:5000/not
flask run
2 3
HTTP/1.0 500 INTERNAL SERVER ERROR
1
from flask import Flask app = Flask(__name__)
2 3 4 5 6 7 8 9
@app.route("/") def main(): return ''' Main bad '''
10 11 12 13 14
@app.route("/bad") def bad(): raise Exception("This is a bad page") return 'Bad page'
15 16 17 18 19
@app.errorhandler(500) def not_found(err): #raise Exception("Oups") return "Our Page crashed", 500
Flask URL routing The mapping of the path part of a URL, so the one that comes after the domain name and after the port number (if it is included) is the path. Mapping that to a function call is called routing.
461
Python Flask
In the following pages we are going to see several examples on how to map routes to functions. It is also called “url route registration”.
Flask Path params 1 2
from flask import Flask, jsonify app = Flask(__name__)
3 4 5 6 7 8 9 10 11
@app.route("/") def main(): return ''' Main
23
42
Joe
'''
12 13 14 15
1
@app.route("/user/") def api_info(uid): return uid
FLASK_APP=app.py FLASK_DEBUG=0
flask run
Flask Path params (int) 1 2
from flask import Flask, jsonify app = Flask(__name__)
3 4 5 6 7 8 9 10 11 12
@app.route("/") def main(): return ''' Main
23
42
Joe
'''
462
Python Flask 13 14 15
1
@app.route("/user/") def api_info(uid): return str(uid)
FLASK_APP=app.py FLASK_DEBUG=0
flask run
Flask Path params add (int) 1 2
from flask import Flask, jsonify app = Flask(__name__)
3 4 5 6 7 8
@app.route("/") def main(): return ''' Main add '''
9 10 11 12
1
@app.route("/add//") def api_info(a, b): return str(a+b)
FLASK_APP=app.py FLASK_DEBUG=0
flask run
Flask Path params add (path) • Accept any path, including slashes:
1 2
from flask import Flask, jsonify app = Flask(__name__)
3 4 5 6 7 8 9 10 11
@app.route("/") def main(): return ''' Main
/user/name
/user/other/dir
/usre/hi.html
'''
463
Python Flask 12 13 14 15
1
@app.route("/user/") def api_info(fullpath): return fullpath
FLASK_APP=app.py FLASK_DEBUG=0
flask run
Jinja loop, conditional, include 1 2 3 4 5 6 7
1 2
. ├── app.py └── templates ├── incl │ ├── footer.html │ └── header.html └── main.html
from flask import Flask, render_template app = Flask(__name__)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
@app.route("/") def main(): languages = [ { "name": "Python", "year": 1991, }, { "name": "JavaScript", "year": 1995, }, { "name": "C", } ] return render_template('main.html', title = "Code Maven Jinja example", languages = languages, )
Python Flask 1
464
{% include 'incl/header.html' %}
2 3 4 5 6 7 8 9 10 11 12 13 14 15
Languages