0% found this document useful (0 votes)
3 views35 pages

Python Handbook

The document is a comprehensive guide to Python programming, covering topics from installation to advanced concepts such as decorators and recursion. It emphasizes Python's popularity due to its simplicity, versatility, and suitability for beginners and professionals alike. The guide also highlights the differences between Python 2 and 3, and provides practical examples for running Python programs and understanding basic syntax and data types.

Uploaded by

rafaelbdb
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views35 pages

Python Handbook

The document is a comprehensive guide to Python programming, covering topics from installation to advanced concepts such as decorators and recursion. It emphasizes Python's popularity due to its simplicity, versatility, and suitability for beginners and professionals alike. The guide also highlights the differences between Python 2 and 3, and provides practical examples for running Python programs and understanding basic syntax and data types.

Uploaded by

rafaelbdb
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

20.

Functions
21. Objects
Flavio Copes 22. Loops
Blog Solopreneur Land Notion to Site Books Bootcamp
22.1. while loop
22.2. for loop
22.3. Break and continue
23. Classes

The Python Handbook 24. Modules


25. The Python Standard Library
26. The PEP8 Python style guide
Table of contents 27. Debugging
28. Variables scope
Table of contents 29. Accept arguments from the command line
1. Introduction to Python 30. Lambda Functions
2. Installing Python 31. Recursion
3. Running Python programs 32. Nested Functions
4. Python 2 vs Python 3 33. Closures
5. The basics of working with Python 34. Decorators
5.1. Variable 35. Docstrings
5.2. Expressions and statement 36. Introspection
5.3. Comment 37. Annotations
5.4. Indentation 38. Exceptions
6. Data Types 39. The with statement
7. Operators 40. Installing 3rd party packages using pip
7.0.1. Assignment operator 41. List comprehensions
7.0.2. Arithmetic operator 42. Polymorphism
7.0.3. Comparison operator 43. Operator Overloading
7.0.4. Boolean operator 44. Virtual Environments
7.0.5. Bitwise operator
7.0.6. is and in
8. The Ternary Operator
1. Introduction to Python
9. Strings
Python is literally eating the programming world. It is growing in popularity
10. Booleans
and usage in ways that are pretty much unprecedented in the history of
11. Numbers
computers.
11.0.1. Integer number
11.0.2. Floating point number There is a huge variety of scenarios that Python excels in. Shell scripting,
11.0.3. Complex number task automation, Web development are just some basic examples.
11.0.4. Arithmetic operations on number
11.0.5. Built-in Function Python is the language of choice for data analysis and machine learning, but
12. Constants it can also adapt to create games and work with embedded devices.
13. Enums
14. User Input Most importantly, it’s the language of choice for introductory computer
15. Control Statements science courses in universities all around the world.
16. Lists
17. Tuples Many students learn Python as their first programming language. Many are
18. Dictionaries learning it right now, many will learn it in the future. And for many of them,
19. Sets Python will be the only programming language they need.
Thanks to this unique position, Python is likely going to grow even more in
the future.

The language is simple, expressive, and it’s quite straightforward.

The ecosystem is huge. There seems to be a library for everything you can
imagine.

Python is a high-level programming language suitable for beginners thanks


to its intuitive syntax, its huge community and vibrant ecosystem.

It is also appreciated by professionals across many different fields.

Technically speaking it is an interpreted language that does not have an


intermediate compilation phase like a compiled language, for example C or
Java.

And like many interpreted languages, it is dynamically typed, which means


that you do not have to indicate the types of the variables you use, and
variables are not tied to a specific type.

Starting with Python is very easy. All you need is to install the official
This has pros and cons. In particular we can mention that you write
package from [Link], for Windows, macOS or Linux, and you’re ready to
programs faster, but on the other hand you have less help from the tools to
go.
prevent possible bugs and you will find out about some kinds of issues only
by executing the program at runtime.
If you are new to programming, in the following posts I will guide you to go
from zero to becoming a Python programmer.
Python supports a wide variety of different programming paradigms,
including procedural programming, object oriented programming and
And even if you are currently a programmer specialized into another
functional programming. It’s flexible enough to adapt to a lot of different
language, Python is a language worth knowing because I think we’re just at
needs.
the start.

Created in 1991 by Guido van Rossum, it’s been rising in popularity -


Lower level languages like C++ and Rust might be great for expert
especially in the past 5 years, as this Google Trends infographic shows:
programmers, but daunting to begin, and they take a long time to master.
Python, on the other hand, is a programming language for programmers, of
course, but also for the non-programmers. The students, the people doing
their day job with Excel, the scientists.

The language everyone interested in coding should learn first.

2. Installing Python
Go to [Link] choose the Downloads menu, choose your
operating system and a panel with a link to download the official package
will appear:
Notice the >>> symbol, and the cursor after that. You can type any Python
code here, and press the enter key to run it.

For example try defining a new variable using

name = "Flavio"

and then print its value, using print():

print(name)

Make sure you follow the specific instructions for your operating system. On
macOS you can find a detailed guide on [Link]
installation-macos/.

3. Running Python programs Note: in the REPL, you can also just type name, press the enter key and
you’ll get the value back. But in a program, you are not going to see any
There are a few different ways to run Python programs. output if you do so - you need to use print() instead.

In particular, you have a distinction between using interactive prompts,


Any line of Python you write here is going to be executed immediately.
where you type Python code and it’s immediately executed, and saving a
Python program into a file, and executing that. Type quit() to exit this Python REPL.

Let’s start with interactive prompts. You can access the same interactive prompt using the IDLE application
that’s installed by Python automatically:
If you open your terminal and type python, you will see a screen like this:

This is the Python REPL (Read-Evaluate-Print-Loop) This might be more convenient for you because with the mouse you can
move around and copy/paste more easily than with the terminal.
Those are the basics that come with Python by default. However I
recommend to install IPython, probably the best command line REPL
application you can find.

Install it with

pip install ipython

Make sure the pip binaries are in your path, then run ipython:

Note that we save Python programs with the .py extension, that’s a
convention.

In this case the program is executed as a whole, not one line at a time. And
that’s typically how we run programs.

We use the REPL for quick prototyping and for learning.

On Linux and macOS a Python program can also be transformed into a shell
script, by prepending all its content with a special line that indicates which
executable to use to run it.

On my system the Python executable is located in /usr/bin/python3, so


I type #!/usr/bin/python3 in the first line:

ipython is another interface to work with a Python REPL, and provides


some nice features like syntax highlighting, code completion, and much
more.

The second way to run a Python program is to write your Python program
code into a file, for example [Link]:

Then I can set execution permission on the file:

chmod u+x [Link]

and then run it with python [Link] and I can run the program with

./[Link]
This is especially useful when you write scripts that interact with the
terminal.

We have many other ways to run Python programs.


Python: Run Python File in Terminal to run the current file in the terminal:
One of them is using VS Code, and in particular the official Python extension
from Microsoft:

Python: Run Current File in Python Interactive Window:

After installing this extension you will have Python code autocompletion and
error checking, automatic formatting and code linting with pylint, and
some special commands, including:

Python: Start REPL to run the REPL in the integrated terminal:


and many more. Just open the command palette (View -> Command
Palette, or Cmd-Shift-P) and type python to see all the Python-related
commands:

and you will be immediately shown an editor with a [Link] file, ready to
Another way to easily run Python code is to use [Link], a very nice website be filled with a lot of Python code:
that provides a coding environment you can create and run your apps on, in
any language, Python included:

Once you have some code, click “Run” to run it on the right side of the
window:

Signup (it’s free), then under “create a repl” click Python:


5. The basics of working with Python
5.1. Variable
We can create a new Python variable by assigning a value to a label, using
the = assignment operator.

In this example we assign a string with the value “Roger” to the name label:

name = "Roger"

Here’s an example with a number:

age = 8

A variable name can be composed by characters, numbers, the _


I think [Link] is handy because: underscore character. It can’t start with a number. These are all valid variable
names:
you can easily share code just by sharing the link
multiple people can work on the same code name1
it can host long-running programs AGE
you can install packages aGE
it provides you a key-value database for more complex applications a11111
my_name

4. Python 2 vs Python 3 _name

One key topic to talk about, right from the start, is the Python 2 vs Python 3 These are invalid variable names:
discussion.
123
Python 3 was introduced in 2008, and it’s been in development as the main
test!
Python version, while Python 2 continued being maintained with bug fixes
name%
and security patches until early 2020.

On that date, Python 2 support was discontinued. Other than that, anything is valid unless it’s a Python keyword. There are
some keywords like for, if, while, import and more.
Many programs are still written using Python 2, and organizations still
actively work on those, because the migration to Python 3 is not trivial and There’s no need to memorize them, as Python will alert you if you use one of
those programs would require a lot of work to upgrade those programs. And those as a variable, and you will gradually recognize them as part of the
large and important migrations always introduce new bugs. Python programming language syntax.

But new code, unless you have to adhere to rules set by your organization 5.2. Expressions and statement
that forces Python 2, should always be written in Python 3.
We can expression any sort of code that returns a value. For example
This book focuses on Python 3.
1 + 1 6. Data Types
"Roger"

Python has several built-in types.


A statement on the other hand is an operation on a value, for example these
are 2 statements: If you create the name variable assigning it the value “Roger”, automatically
this variable is now representing a String data type.

name = "Roger"
print(name) name = "Roger"

A program is formed by a series of statements. Each statement is put on its You can check which type a variable is using the type() function, passing
own line, but you can use a semicolon to have more than one statement on the variable as an argument, and then comparing the result to str:
a single line:
name = "Roger"

name = "Roger"; print(name) type(name) == str #True

Or using isinstance():
5.3. Comment
In a Python program, everything after a hash mark is ignored, and name = "Roger"

considered a comment: isinstance(name, str) #True

#this is a commented line Notice that to see the True value in Python, outside of a REPL, you need to
wrap this code inside print(), but for clarity reasons I avoid using it
name = "Roger" # this is an inline comment
We used the str class here, but the same works for other data types.

5.4. Indentation First, we have numbers. Integer numbers are represented using the int
class. Floating point numbers (fractions) are of type float:
Indentation in Python is meaningful.

age = 1
You cannot indent randomly like this:
type(age) == int #True

name = "Flavio"
print(name) fraction = 0.1
type(fraction) == float #True

Some other languages do not have meaningful whitespace, but in Python,


indentation matters. You saw how to create a type from a value literal, like this:

In this case, if you try to run this program you would get a name = "Flavio"
IndentationError: unexpected indent error, because indenting age = 20
has a special meaning.

Python automatically detects the type from the value type.


Everything indented belongs to a block, like a control statement or
conditional block, or a function or class body. We’ll see more about those
You can also create a variable of a specific type by using the class
later on.
constructor, passing a value literal or a variable name:
name = str("Flavio") plus some interesting ones like is and in.
anotherName = str(name)
7.0.1. Assignment operator
You can also convert from one type to another by using the class
The assignment operator is used to assign a value to a variable:
constructor. Python will try to determine the correct value, for example
extracting a number from a string:
age = 8

age = int("20")
print(age) #20 Or to assign a variable value to another variable:

fraction = 0.1 age = 8


intFraction = int(fraction) anotherVariable = age
print(intFraction) #0

Since Python 3.8, the := walrus operator is used to assign a value to a


This is called casting. Of course this conversion might not always work variable as part of another operation. For example inside an if or in the
depending on the value passed. If you write test instead of 20 in the above conditional part of a loop. More on that later.
string, you’ll get a ValueError: invalid literal for int() with
base 10: 'test' error. 7.0.2. Arithmetic operator
Those are just the basics of types. We have a lot more types in Python: Python has a number of arithmetic operators: +, -, *, / (division), %
(remainder), ** (exponentiation) and // (floor division):
complex for complex numbers
bool for booleans
1 + 1 #2
list for lists
2 - 1 #1
tuple for tuples
2 * 2 #4
range for ranges 4 / 2 #2
dict for dictionaries 4 % 3 #1
set for sets 4 ** 2 #16
4 // 2 #2
and more!

We’ll explore them all soon. Note that you don’t need a space between the operands, but it’s good for
readability.

7. Operators - also works as a unary minus operator:

Python operators are symbols that we use to run operations upon values
print(-4) #-4
and variables.

We can divide operators based on the kind of operation they perform: + is also used to concatenate String values:

assignment operator "Roger" + " is a good dog"


arithmetic operators #Roger is a good dog
comparison operators
logical operators
We can combine the assignment operator with arithmetic operators:
bitwise operators
+= condition1 = True
-= condition2 = False
*=
/= not condition1 #False
%= condition1 and condition2 #False
..and so on condition1 or condition2 #True

Example:
Otherwise, pay attention to a possible source of confusion.

age = 8 or used in an expression returns the value of the first operand that is not a
age += 1
falsy value (False, 0, '', []..). Otherwise it returns the last operand.
# age is now 9

print(0 or 1) ### 1
7.0.3. Comparison operator print(False or 'hey') ### 'hey'
print('hi' or 'hey') ### 'hi'
Python defines a few comparison operators: print([] or False) ### False
print(False or []) ### []
==
!=
The Python docs describe it as if x is false, then y, else x.
>
< and only evaluates the second argument if the first one is true. So if the first
>= argument is falsy (False, 0, '', []..), it returns that argument. Otherwise it
<= evaluates the second argument:

You can use those operators to get a boolean value (True or False)
print(0 and 1) ### 0
depending on the result:
print(1 and 0) ### 0
print(False and 'hey') ### False
a = 1
print('hi' and 'hey') ### 'hey'
b = 2
print([] and False ) ### []
print(False and [] ) ### False
a == b #False
a != b #True
The Python docs describe it as if x is false, then x, else y.
a > b #False
a <= b #True
7.0.5. Bitwise operator
7.0.4. Boolean operator Some operators are used to work on bits and binary numbers:

Python gives us the following boolean operators: & performs binary AND
| performs binary OR
not ^ performs a binary XOR operation
and ~ performs a binary NOT operation
or
<< shift left operation
>> shift right operation
When working with True or False attributes, those work like logical AND,
OR and NOT, and are often used in the if conditional expression evaluation:
Bitwise operators are rarely used, only in very specific situations, but they name = "Roger"
are worth mentioning.

You can concatenate two strings using the + operator:


7.0.6. is and in

is is called the identity operator. It is used to compare two objects and phrase = "Roger" + " is a good dog"

returns true if both are the same object. More on objects later.
You can append to a string using +=:
in is called the membership operator. Is used to tell if a value is contained
in a list, or another sequence. More on lists and other sequences later. name = "Roger"
name += " is a good dog"
8. The Ternary Operator
print(name) #Roger is a good dog
The ternary operator in Python allows you to quickly define a conditional.
You can convert a number to a string using the str class constructor:
Let’s say you have a function that compares an age variable to the 18 value,
and return True or False depending on the result.
str(8) #"8"

Instead of writing:
This is essential to concatenate a number to a string:
def is_adult(age):
if age > 18: print("Roger is " + str(8) + " years old") #Roger is 8 years old
return True
else:
A string can be multi-line when defined with a special syntax, enclosing the
return False
string in a set of 3 quotes:

You can implement it with the ternary operator in this way: print("""Roger is

def is_adult(age): 8
return True if age > 18 else False
years old
""")
First you define the result if the condition is True, then you evaluate the
condition, then you define the result if the condition is false:
#double quotes, or single quotes

<result_if_true> if <condition> else <result_if_false>


print('''
Roger is

9. Strings
8

A string in Python is a series of characters enclosed into quotes or double


quotes: years old
''')

"Roger"
'Roger' A string has a set of built-in methods, like:

You can assign a string value to a variable:


isalpha() to check if a string contains only characters and is not "Ro"Ger" will not work, as Python will think the string ends at "Ro".
empty
isalnum() to check if a string contains characters or digits and is not The way to go is to escape the double quote inside the string, with the \
empty backslash character:
isdecimal() to check if a string contains digits and is not empty
lower() to get a lowercase version of a string name = "Ro\"ger"
islower() to check if a string is lowercase
upper() to get an uppercase version of a string This applies to single quotes too \', and for special formatting characters
isupper() to check if a string is uppercase like \t for tab, \n for new line and \\ for the backslash.
title() to get a capitalized version of a string
startsswith() to check if the string starts with a specific substring Given a string, you can get its characters using square brackets to get a
endswith() to check if the string ends with a specific substring specific item, given its index, starting from 0:
replace() to replace a part of a string
split() to split a string on a specific character separator name = "Roger"
strip() to trim the whitespace from a string name[0] #'R'
join() to append new letters to a string name[1] #'o'
find() to find the position of a substring name[2] #'g'

and many more.


Using a negative number will start counting from the end:
None of those methods alter the original string. They return a new, modified
string instead. For example: name = "Roger"
name[-1] #"r"

name = "Roger"
print([Link]()) #"roger" You can also use a range, using what we call slicing:
print(name) #"Roger"

name = "Roger"

You can use some global functions to work with strings, too. name[0:2] #"Ro"
name[:2] #"Ro"
In particular I think of len(), which gives you the length of a string: name[2:] #"ger"

name = "Roger"
print(len(name)) #5
10. Booleans
Python provides the bool type, which can have two values: True and
The in operator lets you check if a string contains a substring: False (capitalized)

name = "Roger" done = False


print("ger" in name) #True done = True

Escaping is a way to add special characters into a string. Booleans are especially useful with conditional control structures like if
statements:
For example, how do you add a double quote into a string that’s wrapped
into double quotes?
done = True

name = "Roger"
if done:
# run some code here Integer numbers are represented using the int class. You can define an
else: integer using a value literal:
# run some other code

age = 8
When evaluating a value for True or False, if the value is not a bool we
have some rules depending on the type we’re checking: You can also define an integer number using the int() constructor:

numbers are always True unless for the number 0


age = int(8)
strings are False only when empty
lists, tuples, sets, dictionaries are False only when empty
To check if a variable is of type int, you can use the type() global
You can check if a value is a boolean in this way: function:

done = True type(age) == int #True


type(done) == bool #True

11.0.2. Floating point number


Or using isinstance(), passing 2 arguments: the variable, and the bool
class: Floating point numbers (fractions) are of type float. You can define an
integer using a value literal:
done = True
isinstance(done, bool) #True fraction = 0.1

The global any() function is also very useful when working with booleans, Or using the float() constructor:
as it returns True if any of the values of the iterable (list, for example)
passed as argument are True: fraction = float(0.1)

book_1_read = True
To check if a variable is of type float, you can use the type() global
book_2_read = False
function:

read_any_book = any([book_1_read, book_2_read])


type(fraction) == float #True

The global all() function is same, but returns True if all of the values
passed to it are True: 11.0.3. Complex number
Complex numbers are of type complex.
ingredients_purchased = True
meal_cooked = False
You can define them using a value literal:

ready_to_serve = all([ingredients_purchased, meal_cooked])


complexNumber = 2+3j

11. Numbers or using the complex() constructor:

Numbers in Python can be of 3 types: int, float and complex.


complexNumber = complex(2, 3)

11.0.1. Integer number


Once you have a complex number, you can get its real and imaginary part:
[Link] #2.0 round(0.12) #0
[Link] #3.0

You can specify a second parameter to set the decimal points precision:
Again, to check if a variable is of type complex, you can use the type()
global function: round(0.12, 1) #0.1

type(complexNumber) == complex #True


Several other math utility functions and constants are provided by the
Python standard library:
11.0.4. Arithmetic operations on number
the math package provides general math functions and constants
You can perform arithmetic operations on numbers, using the arithmetic the cmath package provides utilities to work with complex numbers.
operators: +, -, *, / (division), % (remainder), ** (exponentiation) and // the decimal package provides utilities to work with decimals and
(floor division): floating point numbers.
the fractions package provides utilities to work with rational numbers

1 + 1 #2
We’ll explore some of those separately later on.
2 - 1 #1
2 * 2 #4
4 / 2 #2 12. Constants
4 % 3 #1
4 ** 2 #16 Python has no way to enforce a variable to be a constant.
4 // 2 #2
The nearest you can go is to use an enum:

and you can use the compound assignment operators


class Constants(Enum):

+= WIDTH = 1024
HEIGHT = 256
-=
*=
/= And get to each value using for example [Link].
%=
..and so on No one can reassign that value.

to quickly perform operations on variables, too: Otherwise if you want to rely on naming conventions, you can adhere to this
one: declare variables that should never change uppercase:
age = 8
age += 1 WIDTH = 1024

No one will prevent to overwrite this value, and Python will not stop it.
11.0.5. Built-in Function
That’s what does most Python code you will see.
There are 2 built-in functions that help with numbers:

abs() returns the absolute value of a number. 13. Enums


round() given a number, returns its value rounded to the nearest integer: Enums are readable names that are bound to a constant value.

To use enums, import Enum from the enum standard library module:
print('Your age is ' + age)
from enum import Enum

This approach gets input at runtime, meaning the program will stop
Then you can initialize a new enum in this way:
execution and will wait until the user types something and presses the
enter key.
class State(Enum):
INACTIVE = 0
You can also do more complex input processing and accept input at
ACTIVE = 1
program invocation time, and we’ll see how to do that later on.

Once you do so, you can reference [Link] and [Link], This works for command line applications. Other kinds of applications will
and they serve as constants. need a different way of accepting input.

Now if you try to print [Link] for example:


15. Control Statements
print([Link]) What’s interesting to do with booleans, and expressions that return a
boolean in particular, is that we can make decisions and take different roads
it will not return 1, but [Link]. depending on their True or False value.

The same value can be reached by the number assigned in the enum: In Python we do so using the if statement:
print(State(1)) will return [Link]. Same for using the square
brackets notation State['ACTIVE']. condition = True

You can however get the value using [Link]. if condition == True:
# do something
You can list all the possible values of an enum:

When the condition test resolves to True, like in the above case, its block
list(State) # [<[Link]: 0>, <[Link]: 1>]
gets executed.

You can count them: What is a block? A block is that part that is indented one level (4 spaces
usually) on the right:
len(State) # 2
condition = True

14. User Input if condition == True:


print("The condition")
In a Python command line application you can display information to the print("was true")
user using the print() function:

The block can be formed by a single line, or multiple lines as well, and it
name = "Roger" ends when you move back to the previous indentation level:
print(name)

condition = True
We can also accept input from the user, using input():
if condition == True:

print('What is your age?') print("The condition")

age = input() print("was true")


print("Hello Syd")
print("Outside of the if") elif name == "Flavio":
print("Hello Flavio")
else:
In combination with if you can have an else block, that’s executed if the
print("The condition")
condition test of if results to False:
print("was False")

condition = True
if and else can also be used in an inline format, which lets us return a
if condition == True: value or another based on a condition.
print("The condition")
print("was True")
Example:
else:
print("The condition") a = 2

print("was False") result = 2 if a == 0 else 3


print(result) # 3

And you can have different linked if checks with elif, that’s executed if
the previous check was False: 16. Lists
condition = True Lists are an essential Python data structure.
name = "Roger"
The allow you to group together multiple values and reference them all with
if condition == True: a common name.
print("The condition")
print("was True") For example:
elif name == "Roger":
print("Hello Roger") dogs = ["Roger", "Syd"]
else:
print("The condition")
A list can hold values of different types:
print("was False")

items = ["Roger", 1, "Syd", True]


The second block in this case is executed if condition is False, and the
name variable value is “Roger”.
You can check if an item is contained into a list with the in operator:

In a if statement you can have just one if and else checks, but multiple
series of elif checks: print("Roger" in items) # True

condition = True A list can also be defined as empty:


name = "Roger"
items = []
if condition == True:
print("The condition")
You can reference the items in a list by their index, starting from zero:
print("was True")
elif name == "Roger":
items[0] # "Roger"
print("Hello Roger")
items[1] # 1
elif name == "Syd":
items[3] # True
Using the same notation you can change the value stored at a specific Remove an item using the remove() method:
index:
[Link]("Test")
items[0] = "Roger"

You can add multiple elements using


You can also use the index() method:
items += ["Test1", "Test2"]
[Link]("Roger") # 0
[Link]("Syd") # 2 #or

[Link](["Test1", "Test2"])
As with strings, using a negative index will start searching from the end:

items[-1] # True These append the item to the end of the list.

To add an item in the middle of a list, at a specific index, use the insert()
You can also extract a part of a list, using slices:
method:

items[0:2] # ["Roger", 1]
[Link](1, "Test") # add "Test" at index 1
items[2:] # ["Syd", True]

To add multiple items at a specific index, you need to use slices:


Get the number of items contained in a list using the len() global function,
the same we used to get the length of a string:
items[1:1] = ["Test1", "Test2"]

len(items) #4
Sort a list using the sort() method:

You can add items to the list by using a list append() method:
[Link]()

[Link]("Test")
Tip: sort() will only work if the list holds values that can be compared.
Strings and integers for example can’t be compared, and you’ll get an error
or the extend() method:
like TypeError: '<' not supported between instances of
'int' and 'str' if you try.
[Link](["Test"])

The sort() methods orders uppercase letters first, then lowercased


You can also use the += operator: letters. To fix this, use:

items += ["Test"] [Link](key=[Link])

# items is ['Roger', 1, 'Syd', True, 'Test'] instead.

Tip: with extend() or += don’t forget the square brackets. Don’t do items Sorting modifies the original list content. To avoid that, you can copy the list
+= "Test" or [Link]("Test") or Python will add 4 individual content using
characters to the list, resulting in ['Roger', 1, 'Syd', True, 'T',
'e', 's', 't'] itemscopy = items[:]
or use the sorted() global function: names[0:2] # ('Roger', 'Syd')
names[1:] # ('Syd',)
print(sorted(items, key=[Link]))

Get the number of items in a tuple using the len() global function, the
that will return a new list, sorted, instead of modifying the original list. same we used to get the length of a string:

17. Tuples len(names) #2

Tuples are another fundamental Python data structure. You can create a sorted version of a tuple using the sorted() global
function:
They allow you to create immutable groups of objects. This means that
once a tuple is created, it can’t be modified. You can’t add or remove items.
sorted(names)

They are created in a way similar to lists, but using parentheses instead of
square brackets: You can create a new tuple from existing tuples using the + operator:

names = ("Roger", "Syd") newTuple = names + ("Vanille", "Tina")

A tuple is ordered, like a list, so you can get its values referencing an index
value:
18. Dictionaries
Dictionaries are a very important Python data structure.
names[0] # "Roger"
names[1] # "Syd" While lists allow you to create collections of values, dictionaries allow you to
create collections of key / value pairs.
You can also use the index() method:
Here is a dictionary example with one key/value pair:

[Link]("Roger") # 0
[Link]("Syd") # 2 dog = { 'name': 'Roger' }

As with strings and lists, using a negative index will start searching from the The key can be any immutable value like a string, a number or a tuple. The
end: value can be anything you want.

A dictionary can contain multiple key/value pairs:


names[-1] # True

dog = { 'name': 'Roger', 'age': 8 }


You can count the items in a tuple with the len() function:

You can access individual key values using this notation:


len(names) # 2

dog['name'] # 'Roger'
You can check if an item is contained into a tuple with the in operator: dog['age'] # 8

print("Roger" in names) # True


Using the same notation you can change the value stored at a specific
index:
You can also extract a part of a tuple, using slices:
dog['name'] = 'Syd' dog['favorite food'] = 'Meat'

And another way is using the get() method, which has an option to add a You can remove a key/value pair from a dictionary using the del statement:
default value:
del dog['favorite food']
[Link]('name') # 'Roger'
[Link]('test', 'default') # 'default'
To copy a dictionary, use the copy() method:

The pop() method retrieves the value of a key, and subsequently deletes dogCopy = [Link]()
the item from the dictionary:

[Link]('name') # 'Roger' 19. Sets


Sets are another important Python data structure.
The popitem() method retrieves and removes the last key/value pair
inserted into the dictionary: We can say they work like tuples, but they are not ordered, and they are
mutable. Or we can say they work like dictionaries, but they don’t have keys.
[Link]()
They also have an immutable version, called frozenset.

You can check if a key is contained into a dictionary with the in operator:
You can create a set using this syntax:

'name' in dog # True


names = {"Roger", "Syd"}

Get a list with the keys in a dictionary using the keys() method, passing its
Sets work well when you think about them as mathematical sets.
result to the list() constructor:

You can intersect two sets:


list([Link]()) # ['name', 'age']

set1 = {"Roger", "Syd"}


Get the values using the values() method, and the key/value pairs tuples set2 = {"Roger"}
using the items() method:
intersect = set1 & set2 #{'Roger'}

print(list([Link]()))
# ['Roger', 8] You can create a union of two sets:

print(list([Link]()))
set1 = {"Roger", "Syd"}
# [('name', 'Roger'), ('age', 8)]
set2 = {"Luna"}

Get a dictionary length using the len() global function, the same we used union = set1 | set2
to get the length of a string or the items in a list: #{'Syd', 'Luna', 'Roger'}

len(dog) #2 You can get the difference between two sets:

You can add a new key/value pair to the dictionary in this way: set1 = {"Roger", "Syd"}
set2 = {"Roger"}
To run this function, we must call it. This is the syntax to call the function:
difference = set1 - set2 #{'Syd'}

hello()
You can check if a set is a superset of another (and of course if a set is a
subset of another) We can execute this function once, or multiple times.

set1 = {"Roger", "Syd"} The name of the function, hello, is very important. It should be descriptive,
set2 = {"Roger"} so anyone calling it can imagine what the function does.

isSuperset = set1 > set2 # True A function can accept one or more parameters:

You can count the items in a set with the len() global function: def hello(name):
print('Hello ' + name + '!')

names = {"Roger", "Syd"}


len(names) # 2 In this case we call the function passing the argument

You can get a list from the items in a set by passing the set to the list() hello('Roger')

constructor:
We call parameters the values accepted by the function inside the function
names = {"Roger", "Syd"} definition, and arguments the values we pass to the function when we call it.
list(names) #['Syd', 'Roger'] It’s common to get confused about this distinction.

An argument can have a default value that’s applied if the argument is not
You can check if an item is contained into a set with the in operator:
specified:

print("Roger" in names) # True


def hello(name='my friend'):
print('Hello ' + name + '!')

20. Functions
hello()
#Hello my friend!
A function lets us create a set of instructions that we can run when needed.

Functions are essential in Python and in many other programming Here’s how we can accept multiple parameters:
languages to create meaningful programs, because they allow us to
decompose a program into manageable parts, they promote readability and def hello(name, age):
code reuse. print('Hello ' + name + ', you are ' + str(age) + ' years old!

Here is an example function called hello that prints “Hello!“:


In this case we call the function passing a set of arguments:
def hello():
print('Hello!') hello('Roger', 8)

This is the function definition. There is a name (hello) and a body, the set Parameters are passed by reference. All types in Python are objects but
of instructions, which is the part that follows the colon and it’s indented one some of them are immutable, including integers, booleans, floats, strings,
level on the right. and tuples. This means that if you pass them as parameters and you modify
their value inside the function, the new value is not reflected outside of the return name, 'Roger', 8
function:
In this case calling hello('Syd') the return value (note: not what it’s
def change(value): printed on screen, but the return value) is a tuple containing those 3 values:
value = 2 ('Syd', 'Roger', 8):

val = 1
def hello(name):
change(val)
print('Hello ' + name + '!')
return name, 'Roger', 8
print(val) #1

If you pass an object that’s not immutable, and you change one of its print(hello('Syd')) #('Syd', 'Roger', 8)
properties, the change will be reflected outside.

A function can return a value, using the return statement. For example in 21. Objects
this case we return the name parameter name:
Everything in Python is an object.

def hello(name):
Even values of basic primitive types (integer, string, float..) are objects. Lists
print('Hello ' + name + '!')
are objects, tuples, dictionaries, everything.
return name

Objects have attributes and methods that can be accessed using the dot
When the function meets the return statement, the function ends. syntax.

We can omit the value: For example, try defining a new variable of type int:

def hello(name): age = 8


print('Hello ' + name + '!')
return
age now has access to the properties and methods defined for all int
objects.
We can have the return statement inside a conditional, which is a common
way to end a function if a starting condition is not met: This includes, for example, access to the real and imaginary part of that
number:
def hello(name):
if not name: print([Link]) # 8
return print([Link]) # 0
print('Hello ' + name + '!')
print(age.bit_length()) #4

If we call the function passing a value that evaluates to False, like an


# the bit_length() method returns the number of bits necessary
empty string, the function is terminated before reaching the print()
# to represent this number in binary notation
statement.

You can return multiple values by using comma separated values: A variable holding a list value has access to a different set of methods:

def hello(name): items = [1, 2]


print('Hello ' + name + '!') [Link](3)
[Link]() #or

age += 1
The methods depend on the type of value.

The id() global function provided by Python lets you inspect the location in and you check with id(age) you will find that age points to a different
memory for a particular object. memory location. The original value has not mutated, we switched to
another value.
id(age) # 140170065725376

22. Loops
Your memory value will change, I am only showing it as an example
Loops are one essential part of programming.
If you assign a different value to the variable, its address will change,
because the content of the variable has been replaced with another value In Python we have 2 kinds of loops: while loops and for loops.
stored in another location in memory:
22.1. while loop
age = 8
while loops are defined using the while keyword, and they repeat their
print(id(age)) # 140535918671808 block until the condition is evaluated as False:

age = 9 condition = True


while condition == True:
print(id(age)) # 140535918671840 print("The condition is True")

But if you modify the object using its methods, the address stays the same: This is an infinite loop. It never ends.

items = [1, 2] Let’s halt the loop right after the first iteration:

print(id(items)) # 140093713593920 condition = True


while condition == True:
[Link](3) print("The condition is True")
condition = False
print(items) # [1, 2, 3]
print(id(items)) # 140093713593920 print("After the loop")

The address only changes if you reassign a variable to another value. In this case, the first iteration is ran, as the condition test is evaluated to
True, and at the second iteration the condition test evaluates to False, so
Some objects are mutable, some are immutable. This depends on the object the control goes to the next instruction, after the loop.
itself. If the object provides methods to change its content, then it’s mutable.
Otherwise it’s immutable. Most types defined by Python are immutable. For It’s common to have a counter to stop the iteration after some number of
example an int is immutable. There are no methods to change its value. If cycles:
you increment the value using
count = 0
age = 8 while count < 10:
age = age + 1 print("The condition is True")
count = count + 1
if item == 2:
print("After the loop") continue
print(item)

22.2. for loop


items = [1, 2, 3, 4]
Using for loops we can tell Python to execute a block for a pre-determined for item in items:
amount of times, up front, and without the need of a separate variable and if item == 2:
conditional to check its value. break
print(item)
For example we can iterate the items in a list:

items = [1, 2, 3, 4]
23. Classes
for item in items:
In addition to using the Python-provided types, we can declare our own
print(item)
classes, and from classes we can instantiate objects.

Or, you can iterate a specific amount of times using the range() function: An object is an instance of a class. A class is the type of an object.

for item in range(04): Define a class in this way:


print(item)
class <class_name>:
# my class
range(4) creates a sequence that starts from 0 and contains 4 items: [0,
1, 2, 3].
For example let’s define a Dog class
To get the index, you should wrap the sequence into the enumerate()
function: class Dog:
# the Dog class
items = [1, 2, 3, 4]
for index, item in enumerate(items):
A class can define methods:
print(index, item)

class Dog:

22.3. Break and continue # the Dog class


def bark(self):

Both while and for loops can be interrupted inside the block, using two print('WOF!')

special keywords: break and continue.


self as the argument of the method points to the current object instance,
continue stops the current iteration and tells Python to execute the next and must be specified when defining a method.
one.
We create an instance of a class, an object, using this syntax:
break stops the loop altogether, and goes on with the next instruction after
the loop end.
roger = Dog()

The first example here prints 1, 3, 4. The second example prints 1:


Now roger is a new object of type Dog.

items = [1, 2, 3, 4]
If you run
for item in items:
[Link]() # 'WOF!'
print(type(roger))

You will get <class '__main__.Dog'> 24. Modules


A special type of method, __init__() is called constructor, and we can Every Python file is a module.
use it to initialize one or more properties when we create a new object from
that class: You can import a module from other files, and that’s the base of any
program of moderate complexity, as it promotes a sensible organization and
class Dog: code reuse.
# the Dog class
def __init__(self, name, age): In the typical Python program, one file acts as the entry point. The other files
[Link] = name
are modules and expose functions that we can call from other files.
[Link] = age
The file [Link] contains this code:

def bark(self):
print('WOF!') def bark():
print('WOF!')

We use it in this way:


We can import this function from another file using import, and once we
roger = Dog('Roger', 8)
do, we can reference the function using the dot notation, [Link]():
print([Link]) # 'Roger'
print([Link]) # 8 import dog

[Link]() # 'WOF!' [Link]()

One important features of classes is inheritance. Or, we can use the from .. import syntax and call the function directly:

We can create an Animal class with a method walk(): from dog import bark

class Animal: bark()


def walk(self):
print('Walking..')
The first strategy allows us to load everything defined in a file.

and the Dog class can inherit from Animal: The second strategy lets us pick the things we need.

Those modules are specific to your program, and importing depends on the
class Dog(Animal):
location of the file in the filesystem.
def bark(self):
print('WOF!')
Suppose you put [Link] in a lib subfolder.

Now creating a new object of class Dog will have the walk() method as In that folder, you need to create an empty file named __init__.py. This
that’s inherited from Animal: tells Python the folder contains modules.

roger = Dog() Now you can choose, you can import dog from lib:
[Link]() # 'Walking..'
from lib import dog or

[Link]() from math import sqrt

sqrt(4) # 2.0
or you can reference the dog module specific function importing from
[Link]:
We’ll soon explore the most important modules individually to understand
what we can do with them.
from [Link] import bark

bark() 26. The PEP8 Python style guide


When you write code, you should adhere to the conventions of the
25. The Python Standard Library programming language you use.

Python exposes a lot of built-in functionality through its standard library. If you learn the right naming and formatting conventions right from the start,
it will be easier to read code written by other people, and people will find
The standard library is a huge collection of all sort of utilities, ranging from your code easier to read.
math utilities to debugging to creating graphical user interfaces.
Python defines its conventions in the PEP8 style guide. PEP stands for
You can find the full list of standard library modules here: Python Enhancement Proposals and it’s the place where all Python
[Link] language enhancements and discussions happen. There are a lot of PEP
proposals, all available at [Link]
Some of the important modules are:
PEP8 is one of the first ones, and one of the most important, too. It defines
math for math utilities the formatting and also some rules on how to write Python in a “pythonic”
re for regular expressions way.
json to work with JSON
datetime to work with dates You can read its full content here: [Link]
sqlite3 to use SQLite 0008/ but here’s a quick summary of the important points you can start
os for Operating System utilities with:
random for random number generation
statistics for statistics utilities Indent using spaces, not tabs
requests to perform HTTP network requests Indent using 4 spaces.
http to create HTTP servers Python files are encoded in UTF-8
urllib to manage URLs Use maximum 80 columns for your code
Write each statement on its own line
Let’s introduce how to use a module of the standard library. You already Functions, variable names and file names are lowercase, with
know how to use modules you create, importing from other files in the underscores between words (snake_case)
program folder. Class names are capitalized, separate words are written with the capital
letter too, (CamelCase)
Well that’s the same with modules provided by the standard library: Package names are lowercase and do not have underscores between
words
import math Variables that should not change (constants) are written in uppercase
Variable names should be meaningful
[Link](4) # 2.0 Add useful comments, but avoid obvious comments
Add spaces around operators
Do not use unnecessary whitespace
Add a blank line before a function If you declare it outside of any function, the variable is visible to any code
Add a blank line between methods in a class running after the declaration, including functions:
Inside functions/methods, blank lines can be used to separate related
blocks of code to help readability age = 8

27. Debugging def test():


print(age)
Debugging is one of the best skills you can learn, as it will help you in many
difficult situations. print(age) # 8
test() # 8
Every language has its debugger. Python has pdb, available through the
standard library. We call it a global variable.

You debug by adding one breakpoint into your code: If you define a variable inside a function, that variable is a local variable, and
it is only visible inside that function. Outside the function, it is not reachable:
breakpoint()

def test():
You can add more breakpoints if needed. age = 8
print(age)
When the Python interpreter hits a breakpoint in your code, it will stop, and it
will tell you what is the next instruction it will run. test() # 8

Then and you can do a few things. print(age)


# NameError: name 'age' is not defined
You can type the name of any variable to inspect its value.

You can press n to step to the next line in the current function. If the code 29. Accept arguments from the command
calls functions, the debugger does not get into them, and consider them
“black boxes”.
line
Python offers several ways to handle arguments passed when we invoke
You can press s to step to the next line in the current function. If the next
the program from the command line.
line is a function, the debugger goes into that, and you can then run one
instruction of that function at a time.
So far you’ve run programs either from a REPL, or using

You can press c to continue the execution of the program normally, without
the need to do it step-by-step. python <filename>.py

You can press q to stop the execution of the program. You can pass additional arguments and options when you do so, like this:

Debugging is useful to evaluate the result of an instruction, and it’s


python <filename>.py <argument1>
especially good to know how to use it when you have complex iterations or
python <filename>.py <argument1> <argument2>
algorithms that you want to fix.

A basic way to handle those arguments is to use the sys module from the
28. Variables scope standard library.

When you declare a variable, that variable is visible in parts of your program,
You can get the arguments passed in the [Link] list:
depending on where you declare it.
import sys You can set an option to have a specific set of values, using choices:
print(len([Link]))
print([Link]) parser.add_argument('-c', '--color', metavar='color', required=True
choices={'red','yellow'}, help='the color to search for')

The [Link] list contains as the first item the name of the file that was
ran, e.g. ['[Link]'].
➜ python python [Link] -c blue

This is a simple way, but you have to do a lot of work. You need to validate usage: [Link] [-h] -c color

arguments, make sure their type is correct, you need to print feedback to the [Link]: error: argument -c/--color: invalid choice: 'blue'

user if they are not using the program correctly. (choose from 'yellow', 'red')

Python provides another package in the standard library to help you: There are more options, but those are the basics.
argparse.
And there are community packages that provide this functionality, too, like
First you import argparse and you call [Link](), Click and Python Prompt Toolkit.
passing the description of your program:

30. Lambda Functions


import argparse

Lambda functions (also called anonymous functions) are tiny functions that
parser = [Link]( have no name and only have one expression as their body.
description='This program prints the name of my dogs'
) In Python they are defined using the lambda keyword:

Then you proceed to add arguments you want to accept. For example in this lambda <arguments> : <expression>
program we accept a -c option to pass a color, like this: python
[Link] -c red
The body must be a single expression. Expression, not a statement.

import argparse This difference is important. An expression returns a value, a statement


does not.
parser = [Link](
description='This program prints a color HEX value' The simplest example of a lambda function is a function that doubles that
) value of a number:

parser.add_argument('-c', '--color', metavar='color', required=True lambda num : num * 2


help='the color to search for')

Lambda functions can accept more arguments:


args = parser.parse_args()

lambda a, b : a * b
print([Link]) # 'red'

Lambda functions cannot be invoked directly, but you can assign them to
If the argument is not specified, the program raises an error: variables:

➜ python python [Link] multiply = lambda a, b : a * b


usage: [Link] [-h] -c color
[Link]: error: the following arguments are required: -c
print(multiply(2, 2)) # 4 This is useful to create utilities that are useful to a function, but not useful
outside of it.
The utility of lambda functions comes when combined with other Python
You might ask: why should I be “hiding” this function, if it does not harm?
functionality, for example in combination with map(), filter() and
reduce().
One, because it’s always best to hide functionality that’s local to a function,
and not useful elsewhere.
31. Recursion
Also, because we can make use of closures (more on this later).
A function in Python can call itself. That’s what recursion is. And it can be
pretty useful in many scenarios. Here is an example:

The common way to explain recursion is by using the factorial calculation. def talk(phrase):
def say(word):
The factorial of a number is the number n mutiplied by n-1, multiplied by n-
print(word)
2… and so on, until reaching the number 1:
words = [Link](' ')
3! = 3 * 2 * 1 = 6 for word in words:
4! = 4 * 3 * 2 * 1 = 24 say(word)
5! = 5 * 4 * 3 * 2 * 1 = 120
talk('I am going to buy the milk')

Using recursion we can write a function that calculates the factorial of any
number: If you want to access a variable defined in the outer function from the inner
function, you first need to declare it as nonlocal:
def factorial(n):
if n == 1: return 1 def count():
return n * factorial(n-1) count = 0

print(factorial(3)) # 6 def increment():


print(factorial(4)) # 24 nonlocal count
print(factorial(5)) # 120 count = count + 1
print(count)

If inside the factorial() function you call factorial(n) instead of


factorial(n-1), you are going to cause an infinite recursion. Python by increment()

default will halt recursions at 1000 calls, and when this limit is reached, you
will get a RecursionError error. count()

Recursion is helpful in many places, and it helps us simplify our code when This is useful especially with closures, as we’ll see later.
there’s no other optimal way to do it, so it’s good to know this technique.

33. Closures
32. Nested Functions
If you return a nested function from a function, that nested function has
Functions in Python can be nested inside other functions. access to the variables defined in that function, even if that function is not
active any more.
A function defined inside a function is visible only inside that function.
Here is a simple counter example.
# do something after
def counter():
return val
count = 0
return wrapper

def increment():
nonlocal count
35. Docstrings
count = count + 1
return count
Documentation is hugely important, not just to communicate to other
people what is the goal of a function/class/method/module, but also to
return increment
yourself.

increment = counter()
When you’ll come back to your code 6 or 12 months from now, you might
not remember all the knowledge you are holding in your head, and reading
print(increment()) # 1
your code and understanding what it is supposed to do, will be much more
print(increment()) # 2
difficult.
print(increment()) # 3

Comments are one way to do so:


We return the increment() inner function, and that has still access to the
state of the count variable even though the counter() function has # this is a comment
ended.
num = 1 #this is another comment

34. Decorators
Another way is to use docstrings.
Decorators are a way to change, enhance or alter in any way how a function
works. The utility of docstrings is that they follow conventions and as such they can
be processed automatically.
Decorators are defined with the @ symbol followed by the decorator name,
just before the function definition. This is how you define a docstring for a function:

Example: def increment(n):


"""Increment a number"""
@logtime return n + 1
def hello():
print('hello!')
This is how you define a docstring for a class and a method:

This hello function has the logtime decorator assigned. class Dog:
"""A class representing a dog"""
Whenever we call hello(), the decorator is going to be called. def __init__(self, name, age):
"""Initialize a new dog"""
A decorator is a function that takes a function as a parameter, wraps the [Link] = name
function in an inner function that performs the job it has to do, and returns [Link] = age
that inner function. In other words:
def bark(self):
def logtime(func): """Let the dog bark"""
def wrapper(): print('WOF!')
# do something before
val = func()
Document a module by placing a docstring at the top of the file, for example I like Google’s standard: [Link]
supposing this is [Link]: pages/[Link]#38-comments-and-docstrings

"""Dog module
Standard allows to have tools to extract docstrings and automatically
generate documentation for your code.
This module does ... bla bla bla and provides the following classes
36. Introspection
- Dog
... Functions, variables and objects can be analyzed using introspection.
"""
First, using the help() global function we can get the documentation if
class Dog: provided in form of docstrings.
"""A class representing a dog"""
def __init__(self, name, age): Then, you can use print() to get information about a function:
"""Initialize a new dog"""
[Link] = name def increment(n):
[Link] = age return n + 1

def bark(self): print(increment)


"""Let the dog bark"""
print('WOF!') # <function increment at 0x7f420e2973a0>

or an object:
Docstrings can span over multiple lines:

class Dog():
def increment(n):
def bark(self):
"""Increment
print('WOF!')
a number
"""
roger = Dog()
return n + 1

print(roger)
Python will process those and you can use the help() global function to
get the documentation for a class/method/function/module. # <__main__.Dog object at 0x7f42099d3340>

For example calling help(increment) will give you this:


The type() function gives us the type of an object:

Help on function increment in module


print(type(increment))
__main__:
# <class 'function'>

increment(n)
print(type(roger))
Increment
# <class '__main__.Dog'>
a number

print(type(1))
There are many different standards to format docstrings, and you can # <class 'int'>
choose to adhere to your favorite one.
print(type('test'))
count: int = 0
# <class 'str'>

Python will ignore those annotations. A separate tool called mypy can be run
The dir() global function lets us find out all the methods and attributes of
standalone, or integrated by IDE like VS Code or PyCharm to automatically
an object:
check for type errors statically, while you are coding, and it will help you
catch type mismatch bugs before even running the code.
print(dir(roger))
A great help especially when your software becomes large and you need to
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', refactor your code.
# '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
# '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__',
38. Exceptions
# '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__'
# '__repr__', '__setattr__', '__sizeof__', '__str__',
It’s important to have a way to handle errors.
# '__subclasshook__', '__weakref__', 'bark']

Python gives us exception handling.

The id() global function shows us the location in memory of any object: If you wrap lines of code into a try: block:

print(id(roger)) # 140227518093024
try:
print(id(1)) # 140227521172384
# some lines of code

It can be useful to check if two variables point to the same object.


If an error occurs, Python will alert you and you can determine which kind of
error occurred using a except blocks:
The inspect standard library module gives us more tools to get
information about objects, and you can check it out here:
try:
[Link]
# some lines of code
except <ERROR1>:
37. Annotations # handler <ERROR1>
except <ERROR2>:
Python is dynamically typed. We do not have to specify the type of a variable # handler <ERROR2>
or function parameter, or a function return value.

Annotations allow us to (optionally) do that. To catch all exceptions you can use except without any error type:

This is a function without annotations: try:


# some lines of code

def increment(n): except <ERROR1>:

return n + 1 # handler <ERROR1>


except:
# catch all other exceptions
This is the same function with annotations:

def increment(n: int) -> int:


The else block is ran if no exceptions were found:
return n + 1
try:
# some lines of code
You can also annotate variables:
except <ERROR1>:
# handler <ERROR1>
try:
except <ERROR2>:
result = 2 / 0
# handler <ERROR2>
except ZeroDivisionError:
else:
print('Cannot divide by zero!')
# no exceptions were raised, the code ran successfully
finally:
result = 1
A finally block lets you perform some operation in any case, regardless if
an error occurred or not print(result) # 1

try: You can raise exceptions in your own code, too, using the raise statement:
# some lines of code
except <ERROR1>:
raise Exception('An error occurred!')
# handler <ERROR1>
except <ERROR2>:
# handler <ERROR2>
This raises a general exception, and you can intercept it using:
else:
# no exceptions were raised, the code ran successfully try:
finally: raise Exception('An error occurred!')
# do something in any case except Exception as error:
print(error)

The specific error that’s going to occur depends on the operation you’re
performing. You can also define your own exception class, extending from Exception:

For example if you are reading a file, you might get an EOFError. If you class DogNotFoundException(Exception):
divide a number by zero you will get a ZeroDivisionError. If you have a pass
type conversion issue you might get a TypeError.

pass here means “nothing” and we must use it when we define a class
Try this code:
without methods, or a function without code, too.

result = 2 / 0
try:
print(result)
raise DogNotFoundException()
except DogNotFoundException:
The program will terminate with an error print('Dog not found!')

Traceback (most recent call last):


File "[Link]", line 1, in <module> 39. The with statement
result = 2 / 0
ZeroDivisionError: division by zero The with statement is very helpful to simplify working with exception
handling.

and the lines of code after the error will not be executed.
For example when working with files, each time we open a file, we must
remember to close it.
Adding that operation in a try: block lets us recover gracefully and move
on with the program:
with makes this process transparent.

Instead of writing:
filename = '/Users/flavio/[Link]' python -m pip install <package>

try:
For example you can install the requests package, a popular HTTP library:
file = open(filename, 'r')
content = [Link]()
pip install requests
print(content)
finally:
[Link]() and once you do, it will be available for all your Python scripts, because
packages are installed globally.

You can write:


The exact location depends on your operating system.

filename = '/Users/flavio/[Link]' On macOS, running Python 3.9, the location is


/Library/Frameworks/[Link]/Versions/3.9/lib/python3.9/site
with open(filename, 'r') as file: packages.
content = [Link]()
print(content) Upgrade a package to its latest version using:

In other words we have built-in implicit exception handling, as close() will pip install –U <package>
be called automatically for us.
Install a specific version of a package using:
with is not just helpful to work with files. The above example is just meant
to introduce its capabilities.
pip install <package>==<version>

40. Installing 3rd party packages using pip Uninstall a package using:

The Python standard library contains a huge number of utilities that simplify
our Python development needs, but nothing can satisfy everything. pip uninstall <package>

That’s why individuals and companies create packages, and make them Show an installed package details, including version, documentation
available as open source software for the entire community. website and author information using:

Those modules are all collected in a single place, the Python Package Index
pip show <package>
available at [Link] and they can be installed on your system using
pip.
41. List comprehensions
There are more than 270.000 packages freely available, at the time of
writing. List comprehensions are a way to create lists in a very concise way.

You should have pip already installed if you followed the Python installation Suppose you have a list:
instructions.
numbers = [1, 2, 3, 4, 5]
Install any package using the command pip install:

You can create a new list using a list comprehension, composed by the
pip install <package>
numbers list elements, power 2:

or, if you do have troubles, you can also run it through python -m:
numbers_power_2 = [n**2 for n in numbers] Operator overloading is an advanced technique we can use to make classes
# [1, 4, 9, 16, 25] comparable and to make them work with Python operators.

Let’s take a class Dog:


List comprehensions are a syntax that’s sometimes preferred over loops, as
it’s more readable when the operation can be written on a single line:
class Dog:
# the Dog class
numbers_power_2 = []
def __init__(self, name, age):
for n in numbers:
[Link] = name
numbers_power_2.append(n**2)
[Link] = age

and over map(): Let’s create 2 Dog objects:

numbers_power_2 = list(map(lambda n : n**2, numbers)) roger = Dog('Roger', 8)


syd = Dog('Syd', 7)

42. Polymorphism
We can use operator overloading to add a way to compare those 2 objects,
Polymorphism generalizes a functionality so it can work on different types. based on the age property:
It’s an important concept in object-oriented programming.
class Dog:
We can define the same method on different classes: # the Dog class
def __init__(self, name, age):
class Dog: [Link] = name
def eat(): [Link] = age
print('Eating dog food') def __gt__(self, other):
return True if [Link] > [Link] else False
class Cat:
def eat():
Now if you try running print(roger > syd) you will get the result True.
print('Eating cat food')

In the same way we defined __gt__() (which means greater than), we can
Then we can generate objects and we can call the eat() method define the following methods:
regardless of the class the object belongs to, and we’ll get different results:
__eq__() to check for equality
animal1 = Dog()
__lt__() to check if an object should be considered lower than
animal2 = Cat() another with the < operator
__le__() for lower or equal (<=)
[Link]() __ge__() for greater or equal (>=)
[Link]() __ne__() for not equal (!=)

Then you have methods to interoperate with arithmetic operations:


We built a generalized interface and we now do not need to know that an
animal is a Cat or a Dog.
__add__() respond to the + operator
__sub__() respond to the – operator
43. Operator Overloading __mul__() respond to the * operator
__truediv__() respond to the / operator
__floordiv__() respond to the // operator
__mod__() respond to the % operator Now running pip will use this virtual environment instead of the global
__pow__() respond to the ** operator environment.
__rshift__() respond to the >> operator
__lshift__() respond to the << operator
__and__() respond to the & operator
__or__() respond to the | operator 🐦 → You can follow me on Twitter
__xor__() respond to the ^ operator
→ Create a site from Notion using Notion to Site
There are a few more methods to work with other operators, but you got the
🏝️→ On Solopreneur Land I talk about starting and running an Internet
idea.
Business as a solo person

44. Virtual Environments 📚 → Read my other ebooks


The C Handbook
It’s common to have multiple Python applications running on your system. The Command Line Handbook
The CSS Handbook
When applications require the same module, at some point you will reach a The Express Handbook
tricky situation where an app needs a version of a module, and another app The Go Handbook
a different version of that same module. The HTML Handbook
The JS Handbook
To solve this, you use virtual environments.
The [Link] Handbook
The [Link] Handbook
We’ll use venv. Other tools work similarly, like pipenv.
The PHP Handbook
The Python Handbook
Create a virtual environment using
The React Handbook
The SQL Handbook
python -m venv .venv
The Svelte Handbook
The Swift Handbook
in the folder where you want to start the project, or where you already have
an existing project.

Then run

source .venv/bin/activate

Use source .venv/bin/[Link] on the Fish shell

Executing the program will activate the Python virtual environment.


Depending on your configuration you might also see your terminal prompt
change.

Mine changed from

➜ folder

to

(.venv) ➜ folder

You might also like