Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This...

57
Python Tutorial Documentation Release 0.1 James Turk October 18, 2016

Transcript of Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This...

Page 1: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial DocumentationRelease 0.1

James Turk

October 18, 2016

Page 2: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Page 3: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Contents

1 Welcome to Python 11.1 About This Tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 What Is Python? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3 A Brief History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.4 How Python Runs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5 Pythonic? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.6 Congratulations! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2 Scalar Types 72.1 Numeric Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.2 Truthiness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.3 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.4 Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.5 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.6 Moving On . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3 Lists, Tuples, Dictionaries 133.1 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133.2 Mutability in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.3 Tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.4 Dicts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.5 Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.6 Next Steps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

4 Control Flow 214.1 if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.2 while Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.3 break and continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.4 for Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224.5 iterables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234.6 Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

5 Functions 275.1 Defining Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275.2 Argument Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285.3 Passing Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295.4 Lambdas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305.5 Decorators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

i

Page 4: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6 Generators and Comprehensions 336.1 Revisiting Iterables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336.2 Generator Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336.3 Comprehensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356.4 map, filter, reduce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366.5 Comprehensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

7 Classes 397.1 Basic Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397.2 Defining Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407.3 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427.4 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437.5 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

8 Modules 498.1 import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498.2 Philosophy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

9 Odds & Ends 519.1 assert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519.2 pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519.3 del . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519.4 global & nonlocal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519.5 with . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519.6 builtins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

10 Indices and tables 53

ii

Page 5: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 1

Welcome to Python

1.1 About This Tutorial

This tutorial is geared at teaching modern Python (and useful libraries) to people that are already somewhat familiarwith programming in another language.

Aiming for a pretty wide range of skill levels in a tutorial like this is challenging, but this tutorial adopts a few strategiesto help:

• One of the most important skills in being a developer is learning through reading code & documentation. Thistutorial will often guide you to external resources to dive deeper.

• While there will be code examples and some exercises, make sure you occassionally start up Python and type incode and reason why something happened. That, combined with understanding how to find and use documen-tation is what will make you a strong developer.

• Often shorter books & tutorials skimp on core concepts in favor of demonstrating syntax, etc. I’m going to takethe opposite approach and try to explain some fo the core concepts being addressed. This is hopefully useful forbeginners to learn from and for more experienced developers to relate what Python is doing to concepts they’realready familiar with.

1.2 What Is Python?

If you read Wikipedia or a typical Python introduction you’ll see it described as an intepreted & dynamically typedlanguage.

You’ll also sometimes hear languages defined in terms of being object-oriented, functional, or procedural. Python,like many of its modern peers, is somewhat agnostic on this front. Python enables development using all three of theseparadigms and a lot of Python code is a blend of styles.

Python is also written with a focus on readability. As we’ll see, this is partially a technical consideration but largelya cultural one. That difference doesn’t make it any less important in defining the character of the language.

These things together make Python what it is, a language that is good for beginners but with enough extensibility thatit is possible to use for a wide variety of applications. in the real world Python is used for everything from simple webapplications to intense scientific applications.

Before we get into what all of these adjectives mean, let’s take a second to understand how Python came to be.

1

Page 6: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

1.3 A Brief History

• December 1989 - Guido van Rossum starts Python as a hobby project. Loosely based on ABC, a teach-ing/prototyping language, but designed to also appeal to Unix/C developers.

• January 1994 - Python 1.0: first major public release. Guido was working on the Computer Programming 4Everyone (CP4E) initiative at Corporation for National Research Initiatives in Reston, VA.

• October 2000 - Python 2.0: switch truly community-driven and the language started down its functional path.Many of the functional elements of Python were introduced around this time.

• December 2008 - Python 3.0: the first release containing major breaking changes since Python 2.0. A ma-jor update that notably changed Python’s handling of unicode. Also fixed many inconsistencies/warts in thelanguage. Because of the amount of Python 2 code out there and the backwards-incompatible nature of thesechanges the transition to Python 3 is still in progress throughout the community. (It started in earnest around thetime of Python 3.3 in 2012.)

For our purposes we’ll use Python 3.5. Though it took longer than anyone hoped, Python 2 is on its way out andPython 2.7 will not be supported past 2020 and most major libraries now support Python 3 and many will soon requireit. It is good however to understand the distinction as you may from time to time find something that requires Python2.

1.4 How Python Runs

As we said before- Python is an interpreted language, much like JavaScript or Ruby. It is somewhat unique in thatit is typically bytecode interpreted, which is why you’ll see .pyc files as you work in your __pycache__ directory.This step allows code to execute somewhat faster but without the necessary compilation step present in languages likeC or Go.

This means that instead of the Python interpreter interpreting your code line by line it first precompiles it to bytecodeor a series of instructions analogous to assembler code. This allows the code to run somewhat faster without theoverhead of parsing the Python syntax at runtime.

To really understand this let’s compare it to some other languages:

1.4.1 C

Steps to run code in a traditional compiled language like C:

• hello.c is compiled, creating an intermediate architecture-specific assembler version (hello.s)

• hello.s is assembled, creating an intermediate ‘object’ file with the platform’s object code (hello.o)

• hello.o is linked with other object files, creating the executable (hello)

• the user runs ./hello - a fully contained executable for their OS/architecture

.----------------.| hello.c |----------------

V/===============\| compiler |\===============/

V.----------------.| hello-x86.s |

2 Chapter 1. Welcome to Python

Page 7: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

----------------V

/===============\| assembler |\===============/

V.--------------------.| hello-x86-osx..o |--------------------

V/===============\| linker |\===============/

V.-------------.| hello | (executable)-------------

1.4.2 JavaScript

Steps to run JS code (on V8):

• JavaScript is run directly within the V8 interpreter without any intermediate step

• while the JS is running the intepreter also JIT (just-in-time) compiles portions of the code directly to architecture-specific machine code

.----------------.| hello.js |----------------

V/=================================\| V8 interpreter & compiler |\=================================/

| ^| |\-------------/

JIT compilation

1.4.3 CPython

.----------------.| hello.py |----------------

V/====================\| Python (compiler) |\====================/

V.----------------.| hello.py c |----------------

V/=======================\| Python (interpreter) |\=======================/

1.4. How Python Runs 3

Page 8: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

Note: Wait, what is CPython?

You’ll sometimes see people refer to CPython. This isn’t a different language, but is likely the version of Pythoninterpreter you’re using.

CPython refers to the implementation of Python that is written largely in C, derived from that initial version releasedyears ago by Guido.

The reason this distinction is made when we talk about the interpreter is do differentiate the language from differentinterpreters that the community has created. The most popular of these is PyPy, an implementaiton of Python largelywritten in Python (mindblowing? yeah). PyPy uses different techniques such as JIT compilation to gain faster speedsthan CPython.

1.4.4 Typing

Python is a strongly & dynamically typed language. This varies from other languages:

If you’re familiar with another interpreted language like JavaScript or Ruby those too are dynamically typed. Alanguage where the following code is valid is generally said to be dynamically typed:

x = "hello"x = 42

Notice we do not declare a type for x, and later when we assign a number to x it doesn’t break anything. This is incontrast to statically typed languages in which types must explicitly be defined (C) or can be inferred but then notchanged (Go).

As for strongly typed, this means that the language is aware of the type of a variable and does not coerce it to otherthings implicitly. This can be contrasted with a language like JavaScript:

x = '3'x = x * 4// x is now 12

Languages like JavaScript are said to be weakly typed (or sometimes untyped).

While strong, weak, dynamic, and static typing all have their advantages and disadvantages, it is good to understandthat in Python’s case types are strong and dynamic.

While not strictly part of the type system, Python APIs also tend to adhere to the principle of duck typing. That is “ifit walks like a duck, and it talks like a duck, then it’s a duck.”

What this means in practical terms is that instead of checking if an object is SomeType we often just check that itadheres to a protocol, that is to say- it has the methods we would expect.

For example:

def print_sorted(thing):thing.sort()print(thing)

>>> print_sorted([3,4,5,1,2])[1,2,3,4,5]

This function could be called with anything that has a .sort() method and is printable.

Contrast this to how this might be written in C:

4 Chapter 1. Welcome to Python

Page 9: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

void print_sorted(int thing[]) {sort_integer_array(thing)print_integer_array(thing)

}

While sometimes you care about the exact type, typically you’ll let these duck-typing situations iron themselves out,our first attempt at print_sorted() is going to be a lot more flexible than:

def print_sorted(thing):if isinstance(thing, list):

thing.sort()print(thing)

else:raise ValueError('can only sort and print lists!')

Which is longer and generally not considered idiomatic Python, or to use an idiom, Pythonic.

1.5 Pythonic?

Like any language, Python developers have a lot of opinions about how to write “good” Python. Keeping theseguidelines in mind will help keep your Python code readable and maintainable.

One thing that is fairly unique is that the opinion is a bit more consistent in Python than in some languages.

These constraints are made more necessary in part because of the flexible nature of Python and they are made possiblein part due to the fact that Python is goverened by a single individual (Guido van Rossum, the Benevolent Dictator ForLife or BDFL) and those he delegates to.

In writing good Python you’ll hear references to PEP 8 and sometimes to the ‘Zen of Python’.

PEP 8 started life a ‘Python Enhancement Proposal’- the means by which language features are proposed and thenultimately decided upon by Guido. It is a formal style guide for the language and should be followed more often thannot. (Though it is worth noting the first section is titled “A Foolish Consistency is the Hobgoblin of Little Minds” –you’ll find pragmatism is a virtue in the Python community.)

Highlights of PEP 8 are:

• Use 4 spaces for indentation, do not use tabs.

• Top level class and function declarations should be preceeded by two blank lines.

• All other declarations should be preceeded by one blank line.

• Operators should be separated from operands by a single space a + b not a+b

• Extra whitespace within parens/braces should be minimized:

– spam(ham[1], {eggs: 2}) - GOOD

– spam( ham[ 1 ], { eggs: 2 } ) - BAD

• Naming:

– ClassNamesLookLikeThis

– function_names_and_variable_names_like_this

– CONSTANTS_LIKE_THIS

– _private_members_preceeded_with_underscore

1.5. Pythonic? 5

Page 10: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

There’s plenty more, and as you become an experienced Python developer you’ll see a lot of code and learn from it.There are also popular source code linters that’ll let you know if your code is foolishly consistent. They can be helpfulespecially in maintaining consistency across large codebases.

The other commonly referenced meaning of “Pythonic” is less practical and more philisophical. It is embodied in thefollowing “poem” which you can see by typing import this:

>>> import this

The Zen of Python, by Tim Peters

Beautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.There should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.Now is better than never.Although never is often better than *right* now.If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea -- let's do more of those!

1.6 Congratulations!

So we’ve covered what it means that Python is interpreted and dynamically typed.

We’ve also talked about the emphasis on readability and the importance Python developers place on making things“pythonic.”

Now you’re ready to actually start learning Python!

We’ll start with Scalar Types.

6 Chapter 1. Welcome to Python

Page 11: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 2

Scalar Types

Python’s types are similar to what you’d find in other dynamic languages. This section will move pretty quickly, justshowing off the major types and an example or two of their usage. It might be worth looking over Python’s built-intypes documentation.

We’ll start with the scalar types. A scalar is a type that can have a single value such as 5, 3.14, or ‘Bob’.

The commonly used scalar types in Python are:

int Any integer.

float Floating point number (64 bit precision)

complex Numbers with an optional imaginary component.

bool True, False

str A sequence of characters (can contain unicode characters).

bytes A sequence of unsigned 8-bit entities, used for manipulating binary data.

NoneType (None) Python’s null or nil equivalent, every instance of None is of NoneType.

2.1 Numeric Types

Like most languages, Python has a separate type for integers and floating point numbers.

Unlike most languages Python’s int type is unbounded. There is no such thing as integer overflow in Python.

Python will do implicit conversions from integer to float when necessary. This makes it possible to add 3 + 2.5without worrying about the fact that they are different types. One perhaps unexpected time this will happen is whendividing:

>>> 10 / 42.5>>> 10 / 25.0

You’ll notice that even when the decimal part is 0, Python will give you a float.

Something that may seem unusual is the complex type. Unless you’re doing mathematical operations you probablywon’t see them but they’re included for completeness. They take the form:

1+2j # 1 is the real component and 2 is the imaginary component.

They can be used like any other variable:

7

Page 12: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> a = 1+2j>>> b = a * 2>>> b(2+4j)

2.2 Truthiness

Unlike the limitless field of numbers. A bool can only take on two values: True or False.

Like many languages, Python has rules for coercion of other values to True and False allowing you to use othertypes where a boolean might be expected (such as an if statement). You can also call bool(var) to cast var toTrue or False explicitly.

The rules for truthiness are as follows (some of these types we haven’t seen yet):

type | false value------------|-----------int | 0float | 0complex | 0+0jstr | ""list | []dict | {}tuple | ()set | set()NoneType | None

2.3 Strings

Strings in Python are much like strings in other languages with first-class support for them. They are sequences ofcharacters, in Python 3’s case they are full Unicode.

a = 'hello world'b = '' # snowmanc = '' # sanskrit

If you’re coming from a language like C or Go, Python has no distinct char or rune type.

Strings can be concatenated with the + operator:

>>> 'hello' + ' ' + 'world''hello world'

It is also possible to use * to repeat a string:

>>> 'hey ' * 3'hey hey hey '

Another common operation is string formatting, the putting other data inside of a string. We do this using the.format method on the string instance.

The way this works is you insert placeholders like {} into the string, and then format() will fill them with itsparameters.

Examples:

8 Chapter 2. Scalar Types

Page 13: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> 'hello {}'.format('world')hello world>>> '{} {}'.format('hello', 'world')hello world>>> '{1} {0}'.format('world', 'hello')hello world>>> '{first} {second}'.format(first='hello', second='world')

As you can see, it is possible to either leave the placeholder blank, in which case it will use its position within thestring to determine the order, or you can explicitly order them or name them. We’ll see how this works when we touchon function arguments.

More on format and other string methods.

2.4 Bytes

Prior to Python 3, Python strings were only allowed to have characters with values betweeen 0-255 (extended ASCII).This made dealing with binary data as a string easy, but dealing with unicode required constant conversion betweenthese strings and (the now removed) unicode type.

In order to make dealing with Unicode easier while still making it possible to deal with binary data, Python 3 intro-duced the bytes type and essentially replaced unicode with str as defined above. bytes have many of the samefeatures as str but without several that don’t make sense such as those related to capitalization.

For now we’ll leave it at that, but know that bytes is there for you when you need to process binary data.

2.5 Operators

Types aren’t much good if we can’t do anything to them. So now’s probably a good time to cover some of the basicoperators.

Commonly used operators:

= Assignment

Arithmetic Operators--------------------+ Addition- Subtraction

* Multiplication/ Division// Floor Division% Modulo

** Power

Comparison Operators--------------------== Equal To> Greater Than>= Greater Than or Equal To< Less Than<= Less Than or Equal To!= Not Equal

2.4. Bytes 9

Page 14: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

Boolean Operators-----------------andornot

Most of these are probably pretty familiar to you, but let’s look at a few more examples:

Notice that we have a division and floor division operator. Many languages treat / as floor division (Python didbetween ints until Python 3)

>>> 3 / 21.5>>> 3 // 21>>> 3.0 // 2.01.0

Another interesting/unexpected feature is that comparisons in Python are chainable:

>>> 1 < 2 < 3True>>> 5 >= 4 == 4True

This lets you set up inequalities without the use of and in many cases:

temp = 98.6

# how you'd typically do a checkif temp > 97.5 and temp < 99.5:

print('pretty reasonable temperature')

# or, perhaps easier to read as a rangeif 97.5 < temp < 99.5:

print('pretty reasonable temperature')

And let’s take a look at Python’s implicit conversion to bools:

>>> 3 and TrueTrue

OK, let’s unpack that. The first statement 3 and True evaluated to True, which is probably what you expected. 3is non-zero, so as per the table above it’ll be considered truthy.

So let’s try:

>>> True and 33

So why when we reverse the order does it return 3?

Python returns the final value evaluated that determines if the statement is True or not. In an and that’ll be the lastvalue if they’re all true.

Because Python ‘short-circuits’, meaning that it stops looking at values once it determines the entire expression willbe false, Python will return the false value if one is false:

>>> 0 and 'the truth'0

10 Chapter 2. Scalar Types

Page 15: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

The or operator obeys the same rules, but short-circuiting rules means it will return the first true value it sees:

>>> '' or 77>>> 'first' or 'second''first'

In practicality this doesn’t often matter too much as and and or are typically used in conditionals if and while,but it can be useful to know.

2.6 Moving On

In the next section we’ll look at the remaining basic types, representing sequences and mappings of other types.

Proceed to Lists, Tuples, Dictionaries.

2.6. Moving On 11

Page 16: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

12 Chapter 2. Scalar Types

Page 17: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 3

Lists, Tuples, Dictionaries

Now that we’re familiar with the scalar types, let’s move on to various collections.

In this section we’re going to cover a few new types:

• list

• dict

• tuple

• set

• frozenset

As well as the concept of mutability.

3.1 Lists

Many languages only have one built-in complex type, commonly referred to as an array. You are probably familiarwith syntax like [1, 2, 3, 4].

In Python, [1,2,3,4] defines what we call a list. A list can also be declared as list(1, 2, 3, 4).

The simplest list is the empty list [].

(It is worth noting that the empty list evaluates to False when used in a boolean context.)

There are a few things we typically want to do with lists:

• retrieve (or set) an item at a specific position via indexing

• check for membership (e.g. does b_list contain the number 2?)

• concatenate two lists together

• get the length of the list

• add an item to the list

• remove an item from the list

3.1.1 Indexing

Like most languages we can also use ourlist[idx] to get and set an item at a specific index:

13

Page 18: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> words = ['green', 'blue', 'red']>>> words[0]'green'>>> words[2] = 'orange'>>> words['green', 'blue', 'orange']

Unlike a lot of other languages, the indexing syntax in Python is quite powerful.

You can get a range of elements using what is called a slice:

>>> words = ['cat', 'dog', 'snake', 'fish', 'elephant']>>> words[1:4]['dog', 'snake', 'fish']

This gets the elements starting at 1 and ending at 3. Note that the range is inclusive on the lower end only. (This seemsodd but is quite helpful when doing math on indices.)

You can also use negative indices, which count from the back of the list:

>>> words = ['cat', 'dog', 'snake', 'fish', 'elephant']>>> words[-1]['elephant']>>> words[1:-1] # trims off first and last['dog', 'snake', 'fish']

You can specify a third part of the slice called the stride. By default the stride is one, meaning it steps through fromstart to end one at a time.

Let’s try changing that:

>>> words = ['cat', 'dog', 'snake', 'fish', 'elephant']>>> words[0:5:2]['cat', 'snake', 'elephant']

That took every other element.

You can omit any part of the slice and it’ll default to start, end and 1. So let’s look at one last example:

>>> words = ['cat', 'dog', 'snake', 'fish', 'elephant']>>> words[::-1]['elephant', 'fish', 'snake', 'dog', 'cat']

3.1.2 Checking For Membership with in

The first thing we’re going to do is to check if an item is a member of a list:

>>> a_list = [1, 2, 3, 4]>>> 4 in a_listTrue>>> 'five' in a_listFalse

This is actually a new operator, in checks for containment in a collection. It can also be used on strings:

>>> 'hello' in 'hello world'True

14 Chapter 3. Lists, Tuples, Dictionaries

Page 19: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

3.1.3 Concatenating Lists

Let’s try +:

>>> a_list = [1, 2, 3, 4]>>> b_list = ['cinco', 'six', 'VII']>>> a_list + b_list[1, 2, 3, 4, 'cinco', 'six', 'VII']

3.1.4 len

There’s a special builtin function to get the length of a list:

>>> len([1, 2, 3, 4])4

3.1.5 Appending & Removing Items

Sometimes you just want to append a single item. There isn’t an operator for this but we’ll use a method of the list:

>>> a_list = [1, 2, 3, 4]>>> a_list.append(5)>>> a_list[1, 2, 3, 4, 5]

And we’ll use .pop() to remove the first item:

>>> a_list.pop()1>>> a_list[2, 3, 4, 5]

Pop by default removes the first item and returns it. You can also pass an argument to pop to remove a different item.

You can also remove items by value using .remove():

>>> a_list = [1, 2, 3, 4]>>> a_list.remove(2)>>> a_list[1, 3, 4]>>> a_list = [2, 2, 2, 2]>>> a_list.remove(2) # will only remove the first occurence>>> a_list[2, 2, 2]

There are plenty of other methods on list to explore.

See the documentation on common sequence operations and mutable sequence types to see the other methods andbuiltins that operate on lists.

3.2 Mutability in Python

Lists are the first Python type that we’ve seen that is “mutable.” A mutable type means that the inner value can change,not just what the variable references. This can be a confusing concept so let’s dive a bit into it:

3.2. Mutability in Python 15

Page 20: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

When we assign a scalar value like x = 7 we are essentially saying that x now has the value 7 until we say otherwise.If we then say y = x we are saying y is 7 too. If we change x later, y does not also change. Here’s a demonstration:

>>> x = 7>>> y = x>>> print('x =', x, ' y =', y)x = 7 y = 7

>>> x = 8>>> print('x =', x, ' y =', y)x = 8 y = 7

>>> y = 9>>> print('x =', x, ' y =', y)x = 8 y = 9

Notice that x and y change independently of one another. This is also true if we do it with any of the other scalar typesfrom Part 1 (str, float, bool, etc.)

We can change what value a variable points to as many times as we like: x = 7, x = "hello", x = 3.14, etc.

Lists offer a different option. If we set x to a list, we can also change the make-up of the list:

>>> x = [1, 2, 3]>>> y = x>>> print('x =', x, ' y =', y)x = [1, 2, 3] y = [1, 2, 3]

>>> x.append(4)>>> print('x =', x, ' y =', y)x = [1, 2, 3, 4] y = [1, 2, 3, 4]

Wait.. what?! y changed when x changed?

What is the difference between this and the above? Why are x and y now linked?

Let’s explore...

>>> x = [1, 2, 3]>>> y = x>>> z = x>>> print('x=', x, ' y=', y, ' z=', z)x= [1, 2, 3] y= [1, 2, 3] z= [1, 2, 3]

>>> # append 4 to x, it will also appear in y and z>>> x.append(4)>>> print('x=', x, ' y=', y, ' z=', z)x= [1, 2, 3, 4] y= [1, 2, 3, 4] z= [1, 2, 3, 4]

>>> # ok at this point all three have changed, let's assign to x now>>> x = [0, 0, 0]>>> print('x=', x, ' y=', y, ' z=', z)x= [0, 0, 0] y= [1, 2, 3, 4] z= [1, 2, 3, 4]

# wait... that time it only changed x?

If the above isn’t making sense to you that’s fine. Let’s think about what we know though:

In our first example with the integers, any time we set x = or y = it didn’t affect the other one.

In our second example, when we called x.append we know that y changed too.

16 Chapter 3. Lists, Tuples, Dictionaries

Page 21: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

In our third example, when we set x = [0, 0, 0] those changes didn’t affect y or z.

The common thread here is the = operator. When we set x to a new value, whether it is an int or list (or anythingelse)- we are creating a new value. When we call a method like x.append(4) though, we are not creating a newvalue but instead modifying (mutating) the underlying array we created when we said x = [1, 2, 3].

It can take some getting used to but there’s a separation between the concept of a value and a variable.

Whenever we define a variable by typing an int, str, float, or list directly (what we call a literal) we’re doing the samething, regardless of what type we’re using:

• x = [1, 2, 3] creates a new list with the value [1, 2, 3] and points x at it.

• y = "hello" creates a new string with the value “hello” and points y at it.

When we assign from one variable to another the behavior varies slightly though:

• x = y when y is immutable means that x now has a copy of the value of y.

• x = y when y is mutable means that x is a reference to the same value as x

This is why we have the ability to modify our list in the above examples, but when we assign a new value to x theother values do not update.

x = 7

variables values

x ---------------------> 7

y = x

variables values

x ---------------------> 7y ---------------------> 7

a = [1, 2, 3]

variables values

x ---------------------> 7y ---------------------> 7a ---------------------> [1, 2, 3]

b = a

variables values

x ---------------------> 7y ---------------------> 7a ---------------------> [1, 2, 3]b ----------/

a.append(4)

variables values

x ---------------------> 7y ---------------------> 7a ---------------------> [1, 2, 3, 4]b ----------/

a = []

3.2. Mutability in Python 17

Page 22: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

variables values

x ---------------------> 7y ---------------------> 7a ---------------------> []b ---------------------> [1, 2, 3, 4]

b = None

variables values

x ---------------------> 7y ---------------------> 7a ---------------------> []b ---------------------> None

[1, 2, 3, 4] *will be deleted*

3.3 Tuples

We saw earlier that a list is an ordered mutable collection. There’s also an ordered immutable collection.

In Python these are called tuples and look very similar to lists, but typically written with () instead of []:

a_list = [1, 'two', 3.0]a_tuple = (1, 'two', 3.0)

Similar to how we used list before, you can also create a tuple via tuple(1,2,3).

The difference being that tuples are immutable. This means no assignment, append, insert, pop, etc. Everything elseworks as it did with lists: indexing, getting the length, checking membership, etc.

Like lists, all of the common sequence operations are available.

Another thing to note is that strictly speaking, the comma is what makes the tuple, not the parentheses. In practice itis a good idea to include the parentheses for clarity and because they are needed in some situations to make operatorprecedence clear.

Let’s look at a quick example:

>>> a_tuple = (1, 2, 3)>>> another_tuple = 1, 2, 3>>> a_tuple == b_tupleTrue

This is also important if you need to make a single element tuple:

>>> x = ('one')>>> y = ('one',)>>> type(x)str>>> type(y)tuple

This is a common gotcha, when a function or setting requires a list or tuple it is easy to forget the trailing commaif you’re passing a single element.

OK, so there are two list-like things and one is just like a list but can’t be modified. Why not use a list all thetime? So why use them if lists do more?

18 Chapter 3. Lists, Tuples, Dictionaries

Page 23: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

• Tuples are lighter-weight and are more memory efficient and often faster if used in appropriate places.

• When using a tuple you protect against accidental modification when passing it between functions.

• Tuples, being immutable, can be used as a key in a dictionary, which we’re about to learn about.

3.4 Dicts

Now with an understanding of mutability we’re ready to discuss Python’s dict type.

Dictionaries are a common feature of modern languages (often known as maps, associative arrays, or hashmaps)which let you associate pairs of values together. The term dictionary is a nod to this, as you can think of them as beingterms/descriptions in a sense.

In Python dict is perhaps the most important type there is, when we learn about modules and classes we’ll see why.

A dictionary declaration might look like this:

birth_year = {'Hamilton': 1755, 'Jefferson': 1743, 'Franklin': 1706, 'Adams': 1735}

Like list there is a second way to declare a dict:

sound = dict(dog='bark', cat='meow', snake='hiss')

And an empty dict can be declared as either {} or dict()

In Python we refer to ‘dog’, ‘cat’, and ‘snake’ as the keys and ‘bark’, ‘meow’, and ‘hiss’ as the values.

A few things we already saw on list work the same for dict:

• Similarly to how we can index into lists we use d[key] to access specific elements in the dict. There are alsoa number of methods available for manipulating & using data from dict.

• len(d) gets the number of item in the dictionary.

• k in d checks if k is a key in the dictionary.

• d.pop(k) pops an item out of the dictionary and returns it, similarly to how list’s pop method worked.

Note: attempting to read from a key that hasn’t been set yet will result in an exception, we’ll cover Exceptionsand reovery from them a bit later

Other commonly used dict methods:

• keys() - returns an iterable of all keys in the dictionary.

• values() - returns an iterable of all values in the dictionary.

• items() - returns an iterable list of (key, value) tuples.

We’ll cover these methods in more detail when we get to for loops and iteration.

Check the Python docs for dict for more details.

3.5 Sets

You may have noticed in the definition of lists above we called them ordered in addition to mutable.

Items in a list have a definite order, which is what allows us to index into them or sort them. Sometimes you don’t carewhat the order of items is, simply whether the collection contains it or not. In this case Python has a special type thatis probably not familiar to you from other languages: set.

3.4. Dicts 19

Page 24: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

A set is an unordered, mutable collection. In math they’re typically denoted with {}, you can use the same in Python.The difference from dict syntax is that there aren’t key-value pairs separated by :.

Many of the same operations you have on lists and tuples are available on set, but anything dealing with order isn’t.This means you can’t index into a set, or pop a specific element. (You can call s.pop() which will pop an arbitraryelement out of s.)

So now we’ve seen an ordered mutable collection (list), an ordered immutable collection (tuple), and an un-ordered mutable collection (set), so you may be wondering if there is an unordered immutable. The answer is thatthere is, and it is called frozenset.

mutable? Ordered UnorderedMutable list setImmutable tuple frozenset

Constructing Sets:

a = {1,2,3} # set literalb = {} # not a set!, ``dict`` literalc = set() # empty setd = frozenset({1,2,3}) # frozensete = frozenset() # empty frozensetf = frozenset([1,1,1,1,1]) # == frozenset({1}), remember- sets cannot contain duplicates

The sequence operations available on list aren’t available, though some basics like len and in still work.

Instead of append, set uses add:

>>> a = {1, 2, 3}>>> a.add(4)>>> a.add(2)>>> a{1, 2, 3, 4}

Common set arithmetic operators are available as methods and operators:

method operatora.issubset(b) a <= ba.issuperset(b) a >= ba.union(b) a | ba.intersection(b) a & ba.difference(b) a - ba.symmetric_difference(b) a ^ ba.isdisjoint(b)

You can check out the Python set documentation for more details and other methods.

3.6 Next Steps

Next we’ll be discussing Control Flow.

20 Chapter 3. Lists, Tuples, Dictionaries

Page 25: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 4

Control Flow

In this section we’ll be covering Python’s various control flow mechanisms.

This includes:

• if

• for

• the concept of iterables

• while, continue, break

• exception handling

4.1 if Statement

Python’s if statement is relatively straightforward. A simple example:

if x < 0:print('negative')

elif x == 0:print('zero')

else:print('positive')

4.2 while Statement

The while statement is also pretty much what you’d expect if you’ve used one in another language:

while condition:do_something()

4.3 break and continue

Within both for and while loops you can use break and continue statements.

Example:

21

Page 26: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> x = 0>>> while True:... x += 1... if x == 3:... continue... print(x)... if x == 5:... break1245

4.4 for Statement

Python’s for statement is also quite simple. It takes the form:

>>> for x in [1, 2, 3]:... print(x)123

It is also possible to attach an else clause to a for loop, the clause will only execute ifthere is no break reachedwithin the loop:

>>> for x in [1, 2, 3]:... print(x)... else:... print(4)1234

>>> for x in ['a', 'b', 'c']... print(x)... if x == 'b':... break... else:... print('x')ab

More generally:

for variable in iterable: loop body

[else: else body

]

As you may expect, variable is the value that changes on each iteration of the loop. So what is iterable?

22 Chapter 4. Control Flow

Page 27: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

4.5 iterables

The simplest iterable is any of the types we covered in the last section: list, tuple, dict, set, frozenset.Strings are also iterable.

Let’s look at some examples. Lists and tuples are straightforward, you’ll iterate over them one element at a time:

>>> for x in [1, 2, 3]:... print(x)123

>>> for x in ('a', 'b', 'c'):... print(x)abc

What about unordered collections like set?

>>> for x in {1, 2, 3}... print(x)231

If you try this locally you might get a different order. Since set isn’t ordered there’s no guarantee on order.

4.5.1 range and enumerate

Sometimes it is useful to iterate over a range of numbers the way you would in other programming languages. Fortu-nately there’s a builtin range() function for just this purpose:

>>> for x in range(3):... print(x)012

The range operator takes up to three arguments. start, stop, step.

You may recall that this is the way that slices worked as well.

A few examples:

>>> for x in range(2, 5):... print(x)234

>>> for x in range(0, 50, 9):... print(x)091827

4.5. iterables 23

Page 28: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

3645

Sometimes it is also useful to know which index in a list you’re at while you iterate. You may think to use range thisway:

>>> my_list = ['first', 'second', 'third']>>> for x in range(len(my_list)):... print(x, my_list[x])0 first1 second2 third

But Python provides a cleaner way using enumerate:

>>> my_list = ['first', 'second', 'third']>>> for i, x in enumerate(my_list):... print(i, x)0 first1 second2 third

You’ll notice that it looks like we’re specifying two variables. In reality enumerate returns a tuple, and we’reusing tuple unpacking to automatically turn that tuple into two variables.

4.5.2 dict Iteration

Similarly, dict is unordered. Iterating over a dict returns the dictionary’s keys:

>>> for x in {'dog': 'woof', 'cat': 'meow', 'duck': 'quack'}:... print(x)dogcatduck

It’s not uncommon to want to iterate over more than just the keys. dict provides three methods to be explicit in whatyou prefer to iterate over:

>>> d = {'dog': 'woof', 'cat': 'meow', 'duck': 'quack'}>>> for x in d.keys():... print(x)duckdogcat

>>> for x in d.values():... print(x)meowquackwoof

>>> for x in d.items():... print(x)('cat', 'meow')('duck', 'quack')('dog', 'woof')

Since items returns tuples we can use tuple unpacking again:

24 Chapter 4. Control Flow

Page 29: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> for k, v in d.items():... print(k, v)cat meowduck quackdog woof

We’ll cover more iterables later when we get to generators, but for now let’s move on to look at other control flowelements.

4.6 Exception Handling

There’s one other form of flow control that is common within Python, exception handling.

You may be familiar with the concept from languages like C++, Java, or JavaScript.

One thing that differs compared to many other languages is that in Python exceptions are relatively lightweight. Thismeans they aren’t only meant to be used in the most extreme circumstances, instead it is not uncommon to use themas a type of control flow.

First let’s look at how Exception handling works:

4.6.1 try & except

Let’s try to access an element that doesn’t exist within a list:

>>> my_list = [1, 2, 3]>>> try:... my_list[99]... except Exception as e:... print(e)list index out of range

the except clause takes the form:

except ExceptionTypes [as variable]

Where ExceptionTypes is one or more Exception names and the optional as variable portion allows storingthe exception for further processing or display.

You can also have multiple except clauses that handle different types differently:

>>> my_list = [1, 2, 3]>>> try:... my_list[99]... except IndexError:... print('index error')... except ValueError:... print('value error')index error

4.6.2 Common Exceptions

BaseException The base exception, catching this will catch all exceptions.

Exception The lowest-level non-system exiting exception. Typically this is the lowest level exception you’d wantto catch.

4.6. Exception Handling 25

Page 30: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

AttributeError Raised when attempting to access an attribute of an object that doesn’t exist. (e.g.x.this_probably_isnt_a_function())

ImportError Raised when something cannot be imported.

IndexError Raised when a sequence index is out of range.

KeyError Raised when trying to access a dictionary key that does not exist.

StopIteration Raised when an iterable is exhausted.

TypeError Raised when an operation is invalid for a specific type.

ValueError Raised when a function receives a value of an appropriate type but inappropriate value.

ZeroDivisionError Raised when attempting to divide by zero.

Check out the full list of built-in exceptions.

You’ll also define your own Exceptions once we get to classes.

4.6.3 else & finally

It is also possible to have two more clauses in a try-except block.

else is called if no exception was caught. finally is caused no matter what, and is useful for cleaning up resources.Here’s an example demonstrating:

try:x / y

except ZeroDivisionError:print('y was zero')

else:print('y was not zero')

finally:print('always prints')

For more on Python exceptions, see the error handling section of the tutorial or the full exception list.

Now that we know basic control flow constructs we’ll look at how Python handles Functions.

26 Chapter 4. Control Flow

Page 31: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 5

Functions

Functions in Python are a lot like functions in other languages with a few major things to note:

• Functions are first-class objects, this means that they can be passed as arguments and treated like any other type.

• All functions return a value, if no return statement is specified then None will be returned.

• It is common to use tuples to in effect return multiple values.

• Functions can take positional and keyword arguments.

• It is possible to define functions that take variable numbers of arguments, and define defaults for arguments.

5.1 Defining Functions

Let’s take a look at a very simple Python function:

>>> def func(a, b=2):... return a + b

This function returns the sum of two arguments. The second argument defaults to 2. Let’s call it a few ways:

>>> func(1, 1)2>>> func(5)7>>> func()TypeError: func() missing 1 required positional argument: 'a'

As you can see, b is optional, but a is not.

We’ve been passing these arguments by position, the first argument is a and the second (if supplied) is b. We can alsopass these arguments by keyword:

>>> func(a=3, b=4)7>>> func(b=4, a=3)7

As you can see, the order doesn’t matter when we pass arguments by keyword. It is common to pass arguments bykeyword when there are many arguments. This makes code both easier to read and less error-prone.

If a function doesn’t return a value explicitly, it will return None:

27

Page 32: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> def say_hello():... print('hello')>>> x = say_hello()hello>>> print(x)None

>>> def pos_or_neg(num):... if num > 0:... return 'pos'... elif num < 0:... return 'neg'>>> print(pos_or_neg(0))None

5.1.1 Warning: Mutable Default Arguments

Let’s say you have a function that has a default argument that would be a mutable object such as a dict or list:

>>> def make_list(item, times, initial=[]):... new_list = initial... for x in range(times):... new_list.append(item)... return new_list>>> make_list(0, 10)[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>> make_list(2, 4)[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2]

That’s probably not what we wanted to happen.

At issue here is that the declaration of the function happens once, whereas the body happens every time it is called.This means initial is set to an empty list once, but persists between calls.

What you’d want to do in this case would be something like:

>>> def make_list(item, times, initial=None):... if initial is None:... initial = [] # this will be a fresh list each call... new_list = initial... for x in range(times):... new_list.append(item)... return new_list>>> make_list(0, 10)[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>> make_list(2, 4)[2, 2, 2, 2]

5.2 Argument Lists

We’ve already seen how to define normal arguments and arguments with optional default values. Let’s look at how wecan define functions that take multiple positional arguments:

>>> def add(*numbers):... total = 0... for num in numbers:

28 Chapter 5. Functions

Page 33: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

... total += num

... return total

*numbers will take any number of positional args and pack them into a single tuple. Let’s try calling our function:

>>> add(1,2)3>>> add(1,2,3)6>>> add(5)5>>> add()0

We can also define functions that take multiple keyword values:

>>> def mash(**monsters):... for name, num in monsters.items():... for x in range(num):... print(name)

**monsters will pack all keyword arguments into a dictionary. For example:

>>> mash(werewolf=4, mummy=3)mummymummymummywerewolfwerewolfwerewolfwerewolf

(Note that because this is a dictionary, order isn’t preserved.)

It is possible to combine all the types of arguments we’ve seen into a single function, but positional arguments mustalways come before keyword arguments. It’s common to see functions like:

def configure_server(hostname, port=80, **kwargs):...

Or even:

def send_message(message, *args, **kwargs):...

There’s nothing special about the names args and kwargs but they’re often used in this context.

5.3 Passing Functions

As mentioned before, functions are first-class objects. They can be passed around just like any other type in Python.

For example:

>>> def add(a, b):... return a + b

>>> def mult(a, b):... return a * b

5.3. Passing Functions 29

Page 34: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> def call_func(f):... print('about to call function', f, 'with 3 and 4')... return f(3, 4)

>>> call_func(add)about to call function <function add at 0x10edc9ea0> with 3 and 4'7>>> call_func(add)about to call function <function mult at 0x10ed27a60> with 3 and 4'12

5.4 Lambdas

Sometimes it is nice to be able to declare a function inline, typically as you pass it to another function.

A common example of this is the builtin sorted function that takes an optional key argument to determine the valueto sort on.

Let’s look at a use case:

>>> animals = ['cat', 'Dog', 'Fish']>>> sorted(animals)['Dog', 'Fish', 'cat']

>>> def lowercase(s):... return s.lower()

>>> sorted(animals, key=lowercase)['cat', 'Dog', 'Fish']

But it’d be nice not to have to define this throwaway lowercase function, so we’ll use a lambda:

>>> sorted(animals, key=lambda s: s.lowercase())['cat', 'Dog', 'Fish']

Lambdas in Python are intentionally constrained. They can take any number of arguments, but the body (after the :)must consist of a single expression which will be considered the return value.

If you find yourself wanting a longer lambda it is generally a better idea to just define a full function. This leads toclearer and more maintainable code.

5.5 Decorators

Sometimes you’ll find yourself with functions resembling:

def check_account_balance(username, password):success = login(username, password)if success:

...else:

raise InvalidUserError()

def set_account_balance(username, password, val):user = login(username, password)if success:

30 Chapter 5. Functions

Page 35: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

...else:

raise InvalidUserError()

It’d be nice not to have that same boiler plate in each function.

This is where decorators come in handy. Decorators allow you to wrap a function call with another, for example:

def login_decorator(oldfunc):def newfunc(username, password, *args, **kwargs):

success = login(username, password)if success:

return oldfunc(username, password, *args, **kwargs)else:

raise InvalidUserError()return newfunc

@login_decoratordef check_account_balance(username, password):

...

@login_decoratordef set_account_balance(username, password, val):

...

This looks a bit scary, but let’s break it down:

• login_decorator is a function that takes a single argument oldfunc, which is the function it is decorating.

• Within this function we’re defining another function newfunc that does our boilerplate and might calloldfunc if appropriate.

• We then use @login_decorator which is the decorator syntax. It is equivalent toset_account_balance = login_decorator(set_account_balance), essentially callingthe function and replacing the old function with it.

Decorators are a powerful concept, when we look at Django we’ll see many uses for them.

For now we’ll move on to Generators and Comprehensions.

5.5. Decorators 31

Page 36: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

32 Chapter 5. Functions

Page 37: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 6

Generators and Comprehensions

Now that we’ve written functions we’re going to look at another type of iterable. Sometimes we want to create aniterable that doesn’t require us storing all of the data in memory. An example would be when we’re trying to iterateover a large file or an iterable that is potentially infinite.

So far we’d iterated over sequences and dictionaries. Creating a list with every line in a 1TB file wouldn’t bedesirable or necessary if we were processing it one line at a time.

In fact we’ve already seen this, let’s take another look at range.

6.1 Revisiting Iterables

If you recall, we can use range to iterate over arbitrary sequences:

>>> for x in range(5):... print(x)01234

But what is range? It looks like a function, maybe it returns a list?

>>> r = range(5)>>> print(r)range(0, 5)>>> type(r)range

What?

It turns out range is a generator. A generator is a function that can return multiple values. Let’s look at how to writeone.

6.2 Generator Functions

In a typical function, the first return statement we reach terminates the function:

33

Page 38: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> def abc():... return 1... return 2... return 3>>> abc()1>>> abc()1

A generator function uses the yield statement instead:

>>> def abc():... yield 1... yield 2... yield 3>>> abc()<generator object abc at 0x10edb6fc0>>>> abc()<generator object abc at 0x10edb7110>

Each time the generator function is called it returns a generator.

You’ll notice each of these generators is at a different memory address, each one is maintaining its own state.

Generators are iterable, just like collections and range.

So we can iterate over the result of a generator function like this:

>>> for x in abc():... print(x)123

We can also store a generator and pass it around. Let’s try passing one to the list function:

>>> gen = abc()>>> list(gen)[1, 2, 3]

That’s a handy way to convert a generator to a sequence type.

What happens if we try to iterate over a generator twice?

>>> gen = abc()>>> list(gen)[1, 2, 3]>>> for x in gen:... print(x)

# nothing prints

Our generator in this case is exhausted, it won’t yield any more values.

It is possible to make infinite generators:

def forever(n):while True:

yield n

You’d need to make sure you used break or raised an exception while iterating over the result of forever(5) oryou’d hang the program.

34 Chapter 6. Generators and Comprehensions

Page 39: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

There’s also a way to just get the next value from the generator, the builtin function next:

>>> gen = abc()>>> gen2 = forever(2)>>> for x in gen:... print(x, next(gen2))1 22 23 2

If you try to call next on an exhausted generator, it’ll raise StopIteration:

>>> gen = abc()>>> next(gen)1>>> next(gen)2>>> next(gen)3>>> next(gen)StopIteration

Generators are extremely powerful, the Python docs for generators explain in more detail.

6.3 Comprehensions

We don’t need to define a function to create a generator, we can also use a generator expression.

A generator expression is a statement in the format:

(expr for var in iterable)

This looks kind of like an inside-out for loop. Let’s look at an example:

>>> gen = (n*2 for n in [1,2,3])>>> for x in gen:... print(x)246

Keep in mind here that [1,2,3] could be anything iterable, including another generator.

We could use this to get the sum of all squares under 100:

>>> sum(i*i for i in range(100))328350

It is also possible to add a conditional:

(expr for var in iterable if truth-expr)

Let’s get the squares of odd numbers:

>>> gen_exp = ((i, i**2) for i in range(10) if i % 2)>>> for n, n2 in gen_exp:... print(n, 'squared is', n2)1 squared is 13 squared is 95 squared is 25

6.3. Comprehensions 35

Page 40: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

7 squared is 499 squared is 81

Notice the addition of the trailing if statement, as well as the fact we’re generating a tuple here.

(Also recall that we’d probably do this by passing the step argument to range in real code, which would avoid theevaluation step here.)

6.4 map, filter, reduce

You have have seen functions with these names in other contexts. These are available in Python but often not usedsince generator expressions provide the same behavior.

Let’s look at some examples:

>>> for i in map(lambda x: x**2, range(5)):... print(i)014916

The first argument of map is a function (often a lambda) and the second is an iterable. The result is an iterable whereeach value is processed through the function.

This is equivalent to the simple generator expression:

>>> for i in (x**2 for x in range(5)):... print(i)014916

filter allows for removing values from the iterable based on a test. For example:

>>> for i in filter(lambda x: x % 2, range(10)):... print(i)13579

This too is equivalent to a generator expression:

>>> for i in (x for x in range(10) if x % 2):... print(i)13579

The above generator expression ((i, i**2) for i in range(10) if i % 2) can be recreated with map& filter:

36 Chapter 6. Generators and Comprehensions

Page 41: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

>>> gen_exp = map(lambda i: (i, i**2), filter(lambda i: i % 2, range(10)))>>> for n, n2 in gen_exp:... print(n, 'squared is', n2)1 squared is 13 squared is 95 squared is 257 squared is 499 squared is 81

But you’ll probably agree that the generator expression looks nicer.

The other function often mentioned with map and filter is reduce.

reduce is a bit different, it takes a function that takes two items and combines them to one, it is called continuouslyon the iterable’s items until a single value is produced. A simple example would be a sum function:

>>> from functools import reduce>>> reduce(lambda a, b: a+b, [1,2,3,4])10

We’ll talk more about import and appropriate uses of reduce later.

6.5 Comprehensions

Earlier we saw an example of using a generator to construct a list. This is a useful thing to be able to do, and there’s amore direct way to get this functionality without making a generator as an intermediary.

Similar to the generator expression, we can use a list comprehension. The only difference is that these list compre-hensions are surrounded by [] instead of parentheses.

Let’s look at some list comprehensions:

>>> [n for n in range(10)][0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> [n*2 for n in range(10) if n*2 < 10][0, 2, 4, 6, 8]

In addition to list comprehensions, there are also set comprehensions and dict comprehensions. These look similar,but just like set and dict differ by whether or not there are (key, value) pairs or not.

Some set comprehensions:

>>> {n*2 for n in range(10) if n*2 < 10}{0, 2, 4, 6, 8}>>> {n for n in [0, 0, 1, 1, 0]}{0, 1}

And dict comprehensions:

>>> {i: i**2 for i in range(10) if i % 2}{1: 1, 3: 9, 5: 25, 7: 49, 9: 81}>>> {word: len(word) for word in ['dog', 'frog', 'python']}{'dog': 3, 'frog': 4, 'python': 6}

Should you want a tuple comprehension you can wrap a generator expression in tuple() or frozenset().

Coming from languages without comprehensions these can look quite foreign, but embracing them can lead to shorterbut also more efficient and readable code. Some books treat comprehensions as an “advanced” concept but hopefullythese examples convince you they can be just as clear as a simple for loop.

6.5. Comprehensions 37

Page 42: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

Take a breath, then let’s dive into Classes.

38 Chapter 6. Generators and Comprehensions

Page 43: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 7

Classes

The tools we’ve seen in the last two chapters are geared towards procedural and functional programming.

As we mentioned up front, Python is a hybrid language that doesn’t force a particular paradigm on you, but it is, at itscore an object based language.

Unlike other object oriented languages like Java, this fact can remain mostly in the background until it is needed. Nowhowever, we’re going to peel back the facade and look at Python’s object system. Let’s start by looking at some thingswe’ve already seen.

7.1 Basic Types

In a few examples we’ve used the builtin type function. Let’s look at how it works:

>>> type(4)int>>> type(lambda: 5)function>>> type(None)NoneType>>> type('hello')str>>> type([1,2,3])list

What are these values coming back from the type function though?

>>> type(type(4))type>>> type(type(type(4)))type

So all of our values we’ve seen so far have a type.

We can also use the builtin isinstance to check if a value if of a certain type:

>>> isinstance(4, int)True>>> isinstance(4.0, int)False

This can be useful when that whole duck-typing thing that we learned about in the introduction doesn’t meet ourneeds. Sometimes you want to be sure you’re dealing with a specific type.

39

Page 44: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

7.1.1 object

Within Python all values are objects. Like in traditional object-oriented languages this means they can have attributesand methods.

We’ve seen a few already, here are some examples:

>>> c = 1+2j>>> c.imag2.0>>> s = 'this is a string'>>> s.title()This Is A String>>> x = 2**8>>> x.bit_length()9

In fact we can even verify this fact using isinstance:

>>> isinstance(4, object)True>>> isinstance('string', object)True>>> isinstance(lambda: 4, object)True

But weren’t all of these things other types?

In fact that’s because isinstance takes the concept of subclasses into account. Something is an instance of a classif it is an instance of that class or a child of that class. Let’s use issubclass to check this out:

>>> issubclass(int, object)True>>> issubclass(str, object)True>>> issubclass(list, object)True

Every type is a subclass of object.

7.2 Defining Classes

Of course, the next step is to define our own types. We do this by using the class keyword.

Let’s start by looking at an example:

class Item:def __init__(self, name, number=0):

self.name = nameself.number = 0

def restock(self, number):self.number += number

def sell_item(self):if self.number > 0:

self.number -= 1else:

raise ValueError("sold out!")

40 Chapter 7. Classes

Page 45: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

Which we’d then use like:

>>> a = Item('corn', 10)>>> a.sell_item()>>> a.number9>>> a.restock(50)>>> a.number59

So let’s break this down:

First we see class Item, this defines the name of our new type. You may also see people write classItem(object):, this was encouraged in Python 2 and works fine in Python 3, but is not required.

We define a few functions inside the class body. These will be methods on the class by default.

The first method we define is __init__, this is the constructor and is the method that will be called when youinstantiate the class via Item(’corn’). Note that we can use our normal function syntax here, including defaultand variadic arguments.

But what’s this first parameter? self This is how Python knows which instance of the class the method is beingcalled upon. Unlike other languages there’s no special this, instead self is passed implicitly. You could name thisvariable anything you wish, but 99% of the time the right thing to call it is self.

We can then assign to and access members on self, there’s no need to declare them but typically you’ll initializethem in the __init__ function so you can use them in other functions without checking if they’ve been defined first.

From there the remaining functions work the same way, just notice that they each take self as their first argument.

7.2.1 Warning: forgetting self

Let’s define our class again but forget self on a method:

class BrokenItem:def __init__(self, name, number=0):

self.name = nameself.number = 0

def restock(number): # Notice the error here.self.number += number

>>> bi = BrokenItem('egg')>>> bi.restock(40)TypeError: sell() takes 1 positional argument but 2 were given

This is a particularly unfriendly error, what is happening here?

When we call bi.restock(40) Python sees it as BrokenItem.restock(bi, 40) - passing the currentinstance of BrokenItem as the first parameter.

Usually this would be assigned to self, but in this case it gets assigned to number, and then the 40 is the mysterysecond positional argument.

It is good to understand this error as it is easy to forget to include self in method definitions, especially if you areswitching between languages.

7.2. Defining Classes 41

Page 46: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

7.3 Properties

If you’re coming from other languages you may be used to writing accessor functions like getName and setCount.In Python we typically don’t write these, allowing people to write directly to members. In the above example thoughmaybe we want to protect the number so that people have to restock & sell through the methods we provide. For thiscase we’d use the following pattern:

class Item:def __init__(self, name, number=0):

self.name = nameself._number = 0 # we modify the name of the instance variable

def restock(self, number):self._number += number

def sell_item(self):if self._number > 0:

self._number -= 1else:

raise ValueError("sold out!")

@propertydef number(self):

return self._number

What we’ve done here is prefix the ‘private’ variable with an underscore, this doesn’t actually prevent anyone fromaccessing it, but is a signal to other developers that it isn’t intended to be accessed directly. All of our internal useshave been updated to use self._number.

We still want people to be able to check the number, so we have added a property. Let’s look at what happens whenwe try to access .number:

>>> i = Item('honey', 10)>>> i.number10>>> i.number = 9AttributeError: can't set attribute

So we’ve effectively made this attribute read-only.

It is also possible to make read-write properties:

class Item:def __init__(self, name, number=0):

self.name = nameself._number = 0 # we modify the name of the instance variable

def restock(self, number):self._number += number

def sell_item(self):if self._number > 0:

self._number -= 1else:

raise ValueError("sold out!")

@propertydef number(self):

return self._number

42 Chapter 7. Classes

Page 47: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

@number.setterdef number(self, value):

if value >= 0:self._number = value

else:raise ValueError('must be non-negative')

Which would use the new function during assignment, guarding against negative values being assigned.

Full property docs.

The actual implementation of property is beyond the scope of what we’ll cover here, they are implementing thedescriptor protocol. (Read more on descriptors).

7.4 Operators

__init__ isn’t the only special method you can define on a class. These are often called magic, double underscore,or dunder methods. These methods are typically called by invoking an operator like + or <=.

Let’s look at an example:

class Animal:def __init__(self, name):

self.name = name

def __add__(self, other):return Animal(self.name + '-' + other.name)

::

>>> cow = Animal('cow')>>> pig = Animal('pig')>>> child = cow + pig>>> child.namecow-pig

>>> child<__main__.Animal at 0x1075071d0>

So __add__ is called when we use the + operator on an Animal.

But what is the deal with that ugly representation of our class?

Let’s add another magic method:

class Animal:def __init__(self, name):

self.name = name

def __add__(self, other):return Animal(self.name + '-' + other.name)

def __repr__(self):return 'Animal: ' + self.name

>>> Animal('cow') + Animal('pig')Animal: cow-pig

7.4. Operators 43

Page 48: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

__repr__ governs what happens when the builtin repr method is called. The method is supposed to return amachine-oriented representation of the class. Often you’ll see these include class names and memory addresses ifthat’s all that Python knows to show. The interactive Python interpreter will display the repr of each statement as wego, which is why overriding it here gives us better output.

You’ll often also want to override __str__ which controls how the instance is converted to a string, for example ina print statement.

Essentially every operator and many of the builtin methods can be overriden by using appropriate methods on theclass.

Here are a few we’ve already seen:

__len__ Overrides the response of the instance to len():

class Snake:def __init__(self, eyes, length):

self.eyes = eyesself.length = length

def __len__(self):return self.length

>>> s = Snake(2, 10)>>> len(s)10

__next__ Can be used to convert a class into a generator:

class Infinite:def __init__(self):

self.n = 0def __next__(self):

self.n += 1return self.n

>>> inf = Infinite()>>> next(inf)1>>> next(inf)2>>> next(inf)3

__call__ Can be used to make a class instance callable as a function:

class AddN:def __init__(self, n):

self.n = ndef __call__(self, val):

return self.n + val

>>> add_five = AddN(5)>>> add_five(3) # invokes __call__8

Python’s datamodel reference covers the entire list.

44 Chapter 7. Classes

Page 49: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

7.5 Inheritance

Like many object oriented languages Python allows classes to inherit from one another.

Inheritance means that a child class will have the same attributes and methods as the parent class, and can add (oroverride) these methods.

Let’s look at an example:

class Square:def __init__(self, w, h):

self.w = wself.h = h

def whoami(self):print('square')

def area(self):return self.w * self.h

class Cube(Square):def __init__(self, w, h, d):

super().__init__(w, h)self.d = d

def whoami(self):print('cube')

def volume(self):return self.w * self.h * self.d

>>> s = Square(3, 4)>>> c = Cube(2, 3, 4)>>> s.whoami()square>>> c.whoami()cube>>> s.area()12>>> c.volume()24>>> isinstance(s, Square)True>>> isinstance(c, Square)True>>> isinstance(s, Cube)False>>> isinstance(c, Cube)True>>> issubclass(Cube, Square)True

A few things to note:

• We use super() to access the parent’s methods. There’s a lot more that super() can do, but in Python 3this is the most common & easiest usage.

• whoami is overridden, if you’re coming from a language like C++ you may notice that this is done without anyspecial syntax (virtual or its ilk)

7.5. Inheritance 45

Page 50: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

• volume is an entirely new method, and only available on the subclass.

• isinstance will tell us that a Cube instance is a Square but not vice versa.

• issubclass operates on types, and helps us verify that Cube is indeed a subclass of Square.

Note that any methods can be overridden, including special __dunder__ methods. In fact, when we define any classwe’re subclassing object and overriding the defaults that it provides.

Just to hammer home this point let’s subclass int and list:

>>> class badint(int):... def __add__(self, other):... return self - other

>>> a = badint(4)>>> a + 5-1

>>> class badlist(list):... def __getitem__(self, index):... return ':P'

>>> b = badlist([1,2,3,4])>>> b[0]':P'>>> b[500]':P'

7.5.1 Multiple Inheritance

It is also possible to have a class subclass multiple other classes. This is known as multiple inheritance and opens upan order of magnitude more confusing situations.

The most important detail is that method calls (and calls to super()) will walk through the “MRO” or methodresolution order. This is generally defined by the order you specify your subclasses.

This means if two subclasses specify a method or attribute with the same name, the one specified first will win. Forexample:

class Color:def __init__(self, name, hex):

self.name = nameself.hex = hex

def identify(self):return 'Color {} ({})'.format(self.name, self.hex)

class Fruit:def __init__(self, name, juicy):

self.name = nameself.juicy = juicy

def identify(self):return 'Fruit {} is {} juicy'.format(self.name, self.juicy)

class Orange(Color, Fruit):def __init__(self):

46 Chapter 7. Classes

Page 51: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

super().__init__('orange', '#ffa500')Fruit.__init__(self, 'orange', 2)

We can see that by default super() called the first listed parent:

>>> o = Orange()>>> o.identify()'Color orange (#ffa500)'

We can explicitly check this via the __mro__ (method resolution order):

>>> Orange.__mro__(__main__.Orange, __main__.Color, __main__.Fruit, object)

Explicit calls to other conflicting properties are possible, but generally avoided:

>>> Fruit.identify(o)'Fruit orange is 2 juicy'

7.5. Inheritance 47

Page 52: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

48 Chapter 7. Classes

Page 53: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 8

Modules

8.1 import

8.2 Philosophy

49

Page 54: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

50 Chapter 8. Modules

Page 55: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 9

Odds & Ends

9.1 assert

9.2 pass

9.3 del

9.4 global & nonlocal

9.5 with

9.6 builtins

https://docs.python.org/3/library/functions.html

51

Page 56: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Python Tutorial Documentation, Release 0.1

52 Chapter 9. Odds & Ends

Page 57: Python Tutorial Documentation · 2019-04-02 · Contents 1 Welcome to Python 1 1.1 About This Tutorial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CHAPTER 10

Indices and tables

• genindex

• modindex

• search

53