Python Essentials 1
Python Essentials 1
Module 1
Introduction to Python and computer programming
the fundamentals of computer programming, i.e., how the computer works, how the
program is executed, how the programming language is defined and constructed;
the difference between compilation and interpretation;
what Python is, how it is positioned among other programming languages, and what
distinguishes the different versions of Python.
A program makes a computer usable. Without a program, a computer, even the most
powerful one, is nothing more than an object. Similarly, without a player, a piano is nothing
more than a wooden box.
Contemporary computers can only evaluate the results of very fundamental operations, like
adding or dividing, but they can do it very fast, and can repeat these actions virtually any
number of times.
Imagine that you want to know the average speed you've reached during a long journey.
You know the distance, you know the time, you need the speed.
Naturally, the computer will be able to compute this, but the computer is not aware of such
things as distance, speed, or time. Therefore, it is necessary to instruct the computer to:
Juniper
Business
Use Only
accept a number representing the distance;
accept a number representing the travel time;
divide the former value by the latter and store the result in the memory;
display the result (representing the average speed) in a readable format.
These four simple actions form a program. Of course, these examples are not formalized,
and they are very far from what the computer can understand, but they are good enough to
be translated into a language the computer can accept.
Another language you use each day is your mother tongue, which you use to manifest your
will and to ponder reality. Computers have their own language, too,
called machine language, which is very rudimentary.
The commands it recognizes are very simple. We can imagine that the computer responds
to orders like "take that number, divide by another and save the result".
No computer is currently capable of creating a new language. However, that may change
soon. Just as people use a number of very different languages, machines have many
different languages, too. The difference, though, is that human languages developed
naturally.
Moreover, they are still evolving, and new words are created every day as old words
disappear. These languages are called natural languages.
Juniper
Business
Use Only
We can say that each language (machine or natural, it doesn't matter) consists of the
following elements:
an alphabet: a set of symbols used to build words of a certain language (e.g., the
Latin alphabet for English, the Cyrillic alphabet for Russian, Kanji for Japanese, and so
on)
a lexis: (aka a dictionary) a set of words the language offers its users (e.g., the word
"computer" comes from the English language dictionary, while "cmoptrue" doesn't;
the word "chat" is present both in English and French dictionaries, but their
meanings are different)
a syntax: a set of rules (formal or informal, written or felt intuitively) used to
determine if a certain string of words forms a valid sentence (e.g., "I am a python" is
a syntactically correct phrase, while "I a python am" isn't)
semantics: a set of rules determining if a certain phrase makes sense (e.g., "I ate a
doughnut" makes sense, but "A doughnut ate me" doesn't)
The IL is, in fact, the alphabet of a machine language. This is the simplest and most
primary set of symbols we can use to give commands to a computer. It's the computer's
mother tongue.
Unfortunately, this mother tongue is a far cry from a human mother tongue. We both
( computers and humans) need something else, a common language for computers and
humans, or a bridge between the two different worlds.
We need a language in which humans can write their programs and a language that
computers may use to execute the programs, one that is far more complex than machine
language and yet far simpler than natural language.
Such languages are often called high-level programming languages. They are at least
somewhat similar to natural ones in that they use symbols, words and conventions readable
to humans. These languages enable humans to express commands to computers that are
much more complex than those offered by ILs.
Juniper
Business
Use Only
alphabetically – a program needs to be written in a recognizable script, such as
Roman, Cyrillic, etc.
lexically – each programming language has its dictionary and you need to master it;
thankfully, it's much simpler and smaller than the dictionary of any natural language;
syntactically – each language has its rules and they must be obeyed;
semantically – the program has to make sense.
Unfortunately, a programmer can also make mistakes with each of the above four senses.
Each of them can cause the program to become completely useless.
Let's assume that you've successfully written a program. How do we persuade the computer
to execute it? You have to render your program into machine language. Luckily, the
translation can be done by a computer itself, making the whole process fast and efficient.
There are two different ways of transforming a program from a high-level programming
language into machine language:
COMPILATION - the source program is translated once (however, this act must be repeated
each time you modify the source code) by getting a file (e.g., an .exe file if the code is
intended to be run under MS Windows) containing the machine code; now you can
distribute the file worldwide; the program that performs this translation is called a compiler
or translator;
INTERPRETATION - you (or any user of the code) can translate the source program each
time it has to be run; the program performing this kind of transformation is called an
interpreter, as it interprets the code every time it is intended to be executed; it also means
that you cannot just distribute the source code as-is, because the end-user also needs the
interpreter to execute it.
There are very few languages that can be both compiled and interpreted. Usually, a
programming language is projected with this factor in its constructors' minds - will it be
compiled or interpreted?
Juniper
Business
Use Only
Note: it has to be pure text, without any decorations like different fonts, colors, embedded
images or other media. Now you have to invoke the interpreter and let it read your source
file.
The interpreter reads the source code in a way that is common in Western culture: from top
to bottom and from left to right. There are some exceptions - they'll be covered later in the
course.
First of all, the interpreter checks if all subsequent lines are correct (using the four aspects
covered earlier).
If the compiler finds an error, it finishes its work immediately. The only result in this case is
an error message.
The interpreter will inform you where the error is located and what caused it. However,
these messages may be misleading, as the interpreter isn't able to follow your exact
intentions, and may detect errors at some distance from their real causes.
For example, if you try to use an entity of an unknown name, it will cause an error, but the
error will be discovered in the place where it tries to use the entity, not where the new
entity's name was introduced.
In other words, the actual reason is usually located a little earlier in the code, for example, in
the place where you had to inform the interpreter that you were going to use the entity of
the name.
If the line looks good, the interpreter tries to execute it (note: each line is usually executed
separately, so the trio "read-check-execute" can be repeated many times - more times than
Juniper
Business
Use Only
the actual number of lines in the source file, as some parts of the code may be executed
more than once).
It is also possible that a significant part of the code may be executed successfully before the
interpreter finds an error. This is normal behavior in this execution model.
You may ask now: which is better? The "compiling" model or the "interpreting" model? There
is no obvious answer. If there had been, one of these models would have ceased to exist a
long time ago. Both of them have their advantages and their disadvantages.
COMPILATION INTERPRETATION
the execution of the
translated code is usually you can run the code as soon as you
faster; complete it - there are no additional
only the user has to have the phases of translation;
compiler - the end-user may the code is stored using
use the code without it; programming language, not machine
ADVANTAGES
the translated code is stored language - this means that it can be
using machine language - as run on computers using different
it is very hard to understand machine languages; you don't
it, your own inventions and compile your code separately for
programming tricks are each different architecture.
likely to remain your secret.
the compilation itself may be
a very time-consuming
don't expect interpretation to ramp
process - you may not be
up your code to high speed - your
able to run your code
code will share the computer's power
immediately after making an
DISADVANTAGES with the interpreter, so it can't be
amendment;
really fast;
you have to have as many
both you and the end user have to
compilers as hardware
have the interpreter to run your code.
platforms you want your
code to be run on.
Python is an interpreted language. This means that it inherits all the described advantages and
disadvantages. Of course, it adds some of its unique features to both sets.
If you want to program in Python, you'll need the Python interpreter. You won't be able to run
your code without it. Fortunately, Python is free. This is one of its most important advantages.
Due to historical reasons, languages designed to be utilized in the interpretation manner are often
called scripting languages, while the source programs encoded using them are called scripts.
What is Python?
Juniper
Business
Use Only
Python is a widely-used, interpreted, object-oriented, and high-level programming language
with dynamic semantics, used for general-purpose programming.
And while you may know the python as a large snake, the name of the Python programming
language comes from an old BBC television comedy sketch series called Monty Python's
Flying Circus.
At the height of its success, the Monty Python team were performing their sketches to live
audiences across the world, including at the Hollywood Bowl.
Since Monty Python is considered one of the two fundamental nutrients to a programmer
(the other being pizza), Python's creator named the language in honor of the TV show.
There are not many languages whose authors are known by name. Python was created
by Guido van Rossum, born in 1956 in Haarlem, the Netherlands. Of course, Guido van
Rossum did not develop and evolve all the Python components himself.
The speed with which Python has spread around the world is a result of the continuous
work of thousands (very often anonymous) programmers, testers, users (many of them
aren't IT specialists) and enthusiasts, but it must be said that the very first idea (the seed
from which Python sprouted) came to one head - Guido's.
In December 1989, I was looking for a "hobby" programming project that would keep me
occupied during the week around Christmas. My office (...) would be closed, but I had a
home computer, and not much else on my hands. I decided to write an interpreter for the
new scripting language I had been thinking about lately: a descendant of ABC that would
appeal to Unix/C hackers. I chose Python as a working title for the project, being in a slightly
irreverent mood (and a big fan of Monty Python's Flying Circus).Guido van Rossum
Python goals
In 1999, Guido van Rossum defined his goals for Python:
Juniper
Business
Use Only
open source, so anyone can contribute to its development;
code that is as understandable as plain English;
suitable for everyday tasks, allowing for short development times.
About 20 years later, it is clear that all these intentions have been fulfilled. Some sources say
that Python is the most popular programming language in the world, while others claim it's
the second or the third.
Either way, it still occupies a high rank in the top ten of the PYPL PopularitY of Programming
Language and the TIOBE Programming Community Index.
Python isn't a young language anymore. It is mature and trustworthy. It's not a one-hit
wonder. It's a bright star in the programming firmament, and time spent learning Python is
a very good investment.
There are many reasons – we've listed some of them already, but let's enumerate them
again in a more practical manner:
it's easy to learn – the time needed to learn Python is shorter than for many other
languages; this means that it's possible to start the actual programming faster;
it's easy to teach – the teaching workload is smaller than that needed by other
languages; this means that the teacher can put more emphasis on general
(language-independent) programming techniques, not wasting energy on exotic
tricks, strange exceptions and incomprehensible rules;
it's easy to use for writing new software – it's often possible to write code faster
when using Python;
it's easy to understand - it's also often easier to understand someone else's code
faster if it is written in Python;
it's easy to obtain, install and deploy – Python is free, open and multiplatform; not
all languages can boast that.
it's not a speed demon – Python does not deliver exceptional performance;
in some cases it may be resistant to some simpler testing techniques – this may
mean that debugging Python code can be more difficult than with other languages;
fortunately, making mistakes is also harder in Python.
Juniper
Business
Use Only
It should also be stated that Python is not the only solution of its kind available on the IT
market.
It has lots of followers, but there are many who prefer other languages and don't even
consider Python for their projects.
Python rivals?
Python has two direct competitors, with comparable properties and predispositions. These
are:
The former is more traditional and more conservative than Python, and resembles some of
the old languages derived from the classic C programming language.
In contrast, the latter is more innovative and more full of fresh ideas than Python. Python
itself lies somewhere between these two creations.
The Internet is full of forums with infinite discussions on the superiority of one of these
three over the others, should you wish to learn more about each of them.
Juniper
Business
Use Only
low-level programming (sometimes called "close to metal" programming): if you
want to implement an extremely effective driver or graphical engine, you wouldn't
use Python;
applications for mobile devices: although this territory is still waiting to be
conquered by Python, it will most likely happen someday.
Python 2 is an older version of the original Python. Its development has since been
intentionally stalled, although that doesn't mean that there are no updates to it. On the
contrary, the updates are issued on a regular basis, but they are not intended to modify the
language in any significant way. They rather fix any freshly discovered bugs and security
holes. Python 2's development path has reached a dead end already, but Python 2 itself is
still very much alive.
Python 3 is the newer (or to be more precise, the current) version of the language. It's
going through its own evolutionary path, creating its own standards and habits.
These two versions of Python aren't compatible with each other. Python 2 scripts won't run
in a Python 3 environment and vice versa, so if you want the old Python 2 code to be run by
a Python 3 interpreter, the only possible solution is to rewrite it, not from scratch, of course,
as large parts of the code may remain untouched, but you do have to revise all the code to
find all possible incompatibilities. Unfortunately, this process cannot be fully automatized.
It's too hard, too time-consuming, too expensive, and too risky to migrate an old Python 2
application to a new platform, and it's even possible that rewriting the code will introduce
new bugs into it. It's easier, and more sensible, to leave these systems alone and to improve
the existing interpreter, instead of trying to work inside the already functioning source code.
If you're modifying an old existing Python solution, then it's highly likely that it was coded in
Python 2. This is the reason why Python 2 is still in use. There are too many existing Python
2 applications to discard it altogether.
NOTE
If you're going to start a new Python project, you should use Python 3, and this is the
version of Python that will be used during this course.
Juniper
Business
Use Only
It is important to remember that there may be smaller or bigger differences between
subsequent Python 3 releases (e.g., Python 3.6 introduced ordered dictionary keys by
default under the CPython implementation) – the good news, though, is that all the newer
versions of Python 3 are backward compatible with the previous versions of Python 3.
Whenever meaningful and important, we will always try to highlight those differences in the
course.
All the code samples you will find during the course have been tested against Python 3.4,
Python 3.6, Python 3.7, and Python 3.8.
First of
all, there are the Pythons which are maintained by the people gathered around the PSF
(Python Software Foundation), a community that aims to develop, improve, expand, and
popularize Python and its environment. The PSF's president is Guido von Rossum himself,
and for this reason, these Pythons are called canonical. They are also considered to
be reference Pythons, as any other implementation of the language should follow all
standards established by the PSF.
Guido van Rossum used the "C" programming language to implement the very first version
of his language and this decision is still in force. All Pythons coming from the PSF are written
in the "C" language. There are many reasons for this approach. One of them (probably the
most important) is that thanks to it, Python may be easily ported and migrated to all
platforms with the ability to compile and run "C" language programs (virtually all platforms
have this feature, which opens up many expansion opportunities for Python).
This is why the PSF implementation is often referred to as CPython. This is the most
influential Python among all the Pythons in the world.
Cython
Juniper
Business
Use Only
Another Python family member is Cython.
Cython
is one of a possible number of solutions to the most painful of Python's traits – the lack of
efficiency. Large and complex mathematical calculations may be easily coded in Python
(much easier than in "C" or any other traditional language), but the resulting code execution
may be extremely time-consuming.
How are these two contradictions reconciled? One solution is to write your mathematical
ideas using Python, and when you're absolutely sure that your code is correct and produces
valid results, you can translate it into "C". Certainly, "C" will run much faster than pure
Python.
This is what Cython is intended to do – to automatically translate the Python code (clean and
clear, but not too swift) into "C" code (complicated and talkative, but agile).
Jython
Another version of Python is called Jython.
"J" is for "Java". Imagine a Python written in Java instead of C. This is useful, for example, if
you develop large and complex systems written entirely in Java and want to add some
Python flexibility to them. The traditional CPython may be difficult to integrate into such an
environment, as C and Java live in completely different worlds and don't share many
common ideas.
Jython can communicate with existing Java infrastructure more effectively. This is why some
projects find it useful and necessary.
Note: the current Jython implementation follows Python 2 standards. There is no Jython
conforming to Python 3, so far.
Juniper
Business
Use Only
PyPy and RPython
Take a look at the logo below. It's a rebus. Can you solve it?
It's a logo of the PyPy - a Python within a Python. In other words, it represents a Python
environment written in Python-like language named RPython (Restricted Python). It is
actually a subset of Python.
The source code of PyPy is not run in the interpretation manner, but is instead translated
into the C programming language and then executed separately.
This is useful because if you want to test any new feature that may be (but doesn't have to
be) introduced into mainstream Python implementation, it's easier to check it with PyPy
than with CPython. This is why PyPy is rather a tool for people developing Python than for
the rest of the users.
This doesn't make PyPy any less important or less serious than CPython, of course.
Juniper
Business
Use Only
In addition, PyPy is compatible with the Python 3 language.
There are many more different Pythons in the world. You'll find them if you look, but this
course will focus on CPython.
Linux users most probably have Python already installed - this is the most likely
scenario, as Python's infrastructure is intensively used by many Linux OS components.
For example, some distributors may couple their specific tools together with the system and
many of these tools, like package managers, are often written in Python. Some parts of
graphical environments available in the Linux world may use Python, too.
python3
If Python 3 is absent, then refer to your Linux documentation in order to find out how to use
your package manager to download and install a new package – the one you need is
named python3 or its name begins with that.
Juniper
Business
Use Only
In this case, select Python 3. The site always offers you the latest version of it.
If you're a Windows user, start the downloaded .exe file and follow all the steps.
Leave the default settings the installer suggests for now, with one exception - look at the
checkbox named Add Python 3.x to PATH and check it.
If you're a macOS user, a version of Python 2 may already have been preinstalled on your
computer, but since we will be working with Python 3, you will still need to download and
install the relevant .pkg file from the Python site.
This will be a very simple procedure, but it should be enough to convince you that the
Python environment is complete and functional.
There are many ways of utilizing Python, especially if you're going to be a Python developer.
an editor which will support you in writing the code (it should have some special
features, not available in simple tools); this dedicated editor will give you more than
the standard OS equipment;
a console in which you can launch your newly written code and stop it forcibly when
it gets out of control;
a tool named a debugger, able to launch your code step-by-step, which will allow
you to inspect it at each moment of execution.
Besides its many useful components, the Python 3 standard installation contains a very
simple but extremely useful application named IDLE.
The first step is to create a new source file and fill it with code. Click File in the IDLE menu
and choose New file.
Juniper
Business
Use Only
As you can see, IDLE opens a new window for you. You can use it to write and amend your
code.
This is the editor window. Its only purpose is to be a workplace in which your source code
is treated. Do not confuse the editor window with the shell window. They perform different
functions.
The editor window is currently untitled, but it's good practice to start work by naming the
source file.
Click File (in the new window), then click Save as..., select a folder for the new file (the
desktop is a good place for your first programming attempts) and chose a name for the new
file.
Juniper
Business
Use Only
Note: don't set any extension for the file name you are going to use. Python needs its files to
have the .py extension, so you should rely on the dialog window's defaults. Using the
standard .py extension enables the OS to properly open these files.
print ("Hisssssss...")
You can use the clipboard to copy the text into the file.
We're not going to explain the meaning of the program right now. You'll find a detailed discussion in the
next chapter.
Take a closer look at the quotation marks. These are the simplest form of quotation marks (neutral,
straight, dumb, etc.) commonly used in source files. Do not try to use typographic quotes (curved, curly,
smart, etc.), used by advanced text processors, as Python doesn’t accept them.
Juniper
Business
Use Only
Save the file (File -> Save) and run the program (Run -> Run Module).
If everything goes okay and there are no mistakes in the code, the console window will show you the
effects caused by running the program.
Juniper
Business
Use Only
How to spoil and fix your code
Now start IDLE again.
Click File, Open, point to the file you saved previously and let IDLE read it in.
Try to run it again by pressing F5 when the editor window is active.
As you can see, IDLE is able to save your code and retrieve it when you need it again.
Hisssssss...
output
Every time you put the closing parenthesis in your program, IDLE will show the part of the text limited
with a pair of corresponding parentheses. This helps you to remember to place them in pairs.
Remove the closing parenthesis again. The code becomes erroneous. It contains a syntax error now. IDLE
should not let you run it.
Juniper
Business
Use Only
Try to run the program again. IDLE will remind you to save the modified file. Follow the instructions.
A new window appears – it says that the interpreter has encountered an EOF (end-of-file) although (in its
opinion) the code should contain some more text.
print ("Hisssssss...")
Let's spoil the code one more time. Remove one letter from the word print. Run the code by
pressing F5. What happens now? As you can see, Python is not able to recognize the instruction.
Juniper
Business
Use Only
How to spoil and fix your code
You may have noticed that the error message generated for the previous error is quite different from the
first one.
This is because the nature of the error is different and the error is discovered at a different stage of
interpretation.
The editor window will not provide any useful information regarding the error, but the console windows
might.
Juniper
Business
Use Only
The message (in red) shows (in the subsequent lines):
the traceback (which is the path that the code traverses through different parts of the program -
you can ignore it for now, as it is empty in such a simple code);
the location of the error (the name of the file containing the error, line number and module
name); note: the number may be misleading, as Python usually shows the place where it first
notices the effects of the error, not necessarily the error itself;
the content of the erroneous line; note: IDLE’s editor window doesn’t show line numbers, but it
displays the current cursor location at the bottom-right corner; use it to locate the erroneous line in
a long source code;
the name of the error and a short explanation.
Experiment with creating new files and running your code. Try to output a different message to the screen,
e.g., roar! , meow , or even maybe an oink! . Try to spoil and fix your code - see what happens.
Python Essentials 1:
Module 2
Data types, variables, basic input-output operations, basic operators
Hello, World!
It's time to start writing some real, working Python code. It'll be very simple for the time
being.
As we're going to show you some fundamental concepts and terms, these snippets of code
won't be serious or complex.
Run the code in the editor window on the right. If everything goes okay here, you'll see
the line of text in the console window.
Juniper
Business
Use Only
Alternatively, launch IDLE, create a new Python source file, fill it with this code, name the file
and save it. Now run it. If everything goes okay, you'll see the rhyme's line in the IDLE
console window. The code you have run should look familiar. You saw something very
similar when we led you through the setting up of the IDLE environment.
Now we'll spend some time showing and explaining to you what you're actually seeing, and
why it looks like this.
As you can see, the first program consists of the following parts:
The print() function
Look at the line of code below:
print("Hello, World!")
The word print that you can see here is a function name. That doesn't mean that wherever the word
appears it is always a function name. The meaning of the word comes from the context in which the word
has been used.
You've probably encountered the term function many times before, during math classes. You can probably
also list several names of mathematical functions, like sine or log.
Python functions, however, are more flexible, and can contain more content than their mathematical
siblings.
A function (in this context) is a separate part of the computer code able to:
cause some effect (e.g., send text to the terminal, create a file, draw an image, play a sound, etc.);
this is something completely unheard of in the world of mathematics;
evaluate a value (e.g., the square root of a value or the length of a given text) and return it as the
function's result; this is what makes Python functions the relatives of mathematical concepts.
Moreover, many of Python functions can do the above two things together.
Juniper
Business
Use Only
Where do the functions come from?
They may come from Python itself; the print function is one of this kind; such a function is an
added value received together with Python and its environment (it is built-in); you don't have to
do anything special (e.g., ask anyone for anything) if you want to make use of it;
they may come from one or more of Python's add-ons named modules; some of the modules come
with Python, others may require separate installation - whatever the case, they all need to be
explicitly connected with your code (we'll show you how to do that soon);
you can write them yourself, placing as many functions as you want and need inside your
program to make it simpler, clearer and more elegant.
The name of the function should be significant (the name of the print function is self-evident).
Of course, if you're going to make use of any already existing function, you have no influence on its name,
but when you start writing your own functions, you should consider carefully your choice of names.
The print() function
As we said before, a function may have:
an effect;
a result.
Mathematical functions usually take one argument, e.g., sin(x) takes an x, which is the measure of an
angle.
Python functions, on the other hand, are more versatile. Depending on the individual needs, they may
accept any number of arguments - as many as necessary to perform their tasks. Note: any number includes
zero - some Python functions don't need any argument.
print("Hello, World!")
In spite of the number of needed/provided arguments, Python functions strongly demand the presence of a
pair of parentheses - opening and closing ones, respectively.
If you want to deliver one or more arguments to a function, you place them inside the parentheses. If
you're going to use a function which doesn't take any argument, you still have to have the parentheses.
Note: to distinguish ordinary words from function names, place a pair of empty parentheses after their
names, even if the corresponding function wants one or more arguments. This is a standard convention.
Juniper
Business
Use Only
Of course it does, but what are they?
The print() function
The only argument delivered to the print() function in this example is a string:
print("Hello, World!")
As you can see, the string is delimited with quotes - in fact, the quotes make the string - they cut out a
part of the code and assign a different meaning to it.
You can imagine that the quotes say something like: the text between us is not code. It isn't intended to be
executed, and you should take it as is.
Almost anything you put inside the quotes will be taken literally, not as code, but as data. Try to play with
this particular string - modify it, enter some new content, delete some of the existing content.
There's more than one way to specify a string inside Python's code, but for now, though, this one is
enough.
So far, you have learned about two important parts of the code: the function and the string. We've talked
about them in terms of syntax, but now it's time to discuss them in terms of semantics.
The print() function
The function name (print in this case) along with the parentheses and argument(s), forms the function
invocation.
Juniper
Business
Use Only
We'll discuss this in more depth soon, but we should just shed a little light on it right now.
What happens when Python encounters an invocation like this one below?
function_name(argument)
Let's see:
First, Python checks if the name specified is legal (it browses its internal data in order to find an
existing function of the name; if this search fails, Python aborts the code);
second, Python checks if the function's requirements for the number of arguments allows you to
invoke the function in this way (e.g., if a specific function demands exactly two arguments, any
invocation delivering only one argument will be considered erroneous, and will abort the code's
execution);
third, Python leaves your code for a moment and jumps into the function you want to invoke; of
course, it takes your argument(s) too and passes it/them to the function;
fourth, the function executes its code, causes the desired effect (if any), evaluates the desired
result(s) (if any) and finishes its task;
finally, Python returns to your code (to the place just after the invocation) and resumes its
execution.
The print() function
Three important questions have to be answered as soon as possible:
takes its arguments (it may accept more than one argument and may also accept less than one
argument)
converts them into human-readable form if needed (as you may suspect, strings don't require this
action, as the string is already readable)
and sends the resulting data to the output device (usually the console); in other words, anything
you put into the print() function will appear on your screen.
No wonder then, that from now on, you'll utilize print() very intensively to see the results of your
operations and evaluations.
Juniper
Business
Use Only
2. What arguments does print() expect?
Any. We'll show you soon that print() is able to operate with virtually all types of data offered by
Python. Strings, numbers, characters, logical values, objects - any of these may be successfully passed
to print() .
The print() function - instructions
You have already seen a computer program that contains one function invocation. A function invocation is
one of many possible kinds of Python instructions.
Of course, any complex program usually contains many more instructions than one. The question is: how
do you couple more than one instruction into the Python code?
Python's syntax is quite specific in this area. Unlike most programming languages, Python requires
that there cannot be more than one instruction in a line.
A line can be empty (i.e., it may contain no instruction at all) but it must not contain two, three or more
instructions. This is strictly prohibited.
Note: Python makes one exception to this rule - it allows one instruction to spread across more than one
line (which may be helpful when your code contains complex constructions).
Let's expand the code a bit, you can see it in the editor. Run it and note what you see in the console.
output
the program invokes the print() function twice, and you can see two separate lines in the
console - this means that print() begins its output from a new line each time it starts its
execution; you can change this behavior, but you can also use it to your advantage;
each print() invocation contains a different string, as its argument and the console content
reflects it - this means that the instructions in the code are executed in the same order in which
they have been placed in the source file; no next instruction is executed until the previous one is
completed (there are some exceptions to this rule, but you can ignore them for now)
Sandbox
Code
print("The itsy bitsy spider climbed up the waterspout.")
print("Down came the rain and washed the spider out.")
Juniper
Business
Use Only
2
3
print("The itsy bitsy spider climbed up the waterspout.")
print("Down came the rain and washed the spider out.")
Console
The print() function - instructions
We've changed the example a bit - we've added one empty print() function invocation.
We call it empty because we haven't delivered any arguments to the function.
What happens?
output
As you can see, the empty print() invocation is not as empty as you may have expected - it
does output an empty line, or (this interpretation is also correct) its output is just a newline.
This is not the only way to produce a newline in the output console. We're now going to
show you another way.
There are two very subtle changes - we've inserted a strange pair of characters inside the rhyme. They look
like this: \n .
The backslash ( \ ) has a very special meaning when used inside strings - this is called the escape
character.
Juniper
Business
Use Only
The word escape should be understood specifically - it means that the series of characters in the string
escapes for the moment (a very short moment) to introduce a special inclusion.
In other words, the backslash doesn't mean anything in itself, but is only a kind of announcement, that the
next character after the backslash has a different meaning too.
The letter n placed after the backslash comes from the word newline.
Both the backslash and the n form a special symbol named a newline character, which
urges the console to start a new output line.
Run the code. Your console should now look like this:
output
As you can see, two newlines appear in the nursery rhyme, in the places where the \n have been used.
Sandbox
Code
print("The itsy bitsy spider\nclimbed up the waterspout.")
print()
print("Down came the rain\nand washed the spider out.")
1
2
3
4
print("The itsy bitsy spider\nclimbed up the waterspout.")
print()
print("Down came the rain\nand washed the spider out.")
Console
The itsy bitsy spider
climbed up the waterspout.
1. If you want to put just one backslash inside a string, don't forget its escaping nature - you
have to double it, e.g., such an invocation will cause an error:
Juniper
Business
Use Only
print("\")
print("\\")
2. Not all escape pairs (the backslash coupled with another character) mean something.
Experiment with your code in the editor, run it, and see what happens.
Look at the editor window. This is what we're going to test now:
There is one print() function invocation, but it contains three arguments. All of them are
strings.
The arguments are separated by commas. We've surrounded them with spaces to make
them more visible, but it's not really necessary, and we won't be doing it anymore.
In this case, the commas separating the arguments play a completely different role than the
comma inside the string. The former is a part of Python's syntax, the latter is intended to be
shown in the console.
If you look at the code again, you'll see that there are no spaces inside the strings.
Juniper
Business
Use Only
The itsy bitsy spider climbed up the waterspout.
output
The spaces, removed from the strings, have appeared again. Can you explain why?
a print() function invoked with more than one argument outputs them all on
one line;
the print() function puts a space between the outputted arguments on its own
initiative.
You should be able to predict the output without running the code in the editor.
The way in which we are passing the arguments into the print() function is the most
common in Python, and is called the positional way (this name comes from the fact that
the meaning of the argument is dictated by its position, e.g., the second argument will be
outputted after the first, not the other way round).
Run the code and check if the output matches your predictions.
We aren't going to explain it in depth right now. We plan to do this when we talk about
functions. For now, we simply want to show you how it works. Feel free to use it in your own
programs.
The mechanism is called keyword arguments. The name stems from the fact that the
meaning of these arguments is taken not from its location (position) but from the special
word (keyword) used to identify them.
The print() function has two keyword arguments that you can use for your purposes. The
first of them is named end .
In the editor window you can see a very simple example of using a keyword argument.
Juniper
Business
Use Only
In order to use it, it is necessary to know some rules:
In our example, we have made use of the end keyword argument, and set it to a string
containing one space.
output
As you can see, the end keyword argument determines the characters the print() function
sends to the output once it reaches the end of its positional arguments.
The default behavior reflects the situation where the end keyword argument
is implicitly used in the following way: end="\n" .
If you look carefully, you'll see that we've used the end argument, but the string assigned to
it is empty (it contains no characters at all).
What will happen now? Run the program in the editor to find out.
As the end argument has been set to nothing, the print() function outputs nothing too,
once its positional arguments have been exhausted.
output
Juniper
Business
Use Only
The string assigned to the end keyword argument can be of any length. Experiment with it if
you want.
My-name-is-Monty-Python.
output
The print() function now uses a dash, instead of a space, to separate the outputted
arguments.
Note: the sep argument's value may be an empty string, too. Try it for yourself.
The example doesn't make much sense, but it visibly presents the interactions
between end and sep .
Now that you understand the print() function, you're ready to consider how to store and
process data in Python.
Estimated time
5-10 minutes
Juniper
Business
Use Only
Level of difficulty
Very Easy
Objectives
becoming familiar with the print() function and its formatting capabilities;
experimenting with Python code.
Scenario
Modify the first line of code in the editor, using the sep and end keywords, to match the
expected output. Use the two print() functions in the editor.
Expected output
Programming***Essentials***in...Python
output
print("Programming","Essentials","in",sep="***",end="...")
print("Python")
Console
Programming***Essentials***in...Python
LAB
Estimated time
5-15 minutes
Level of difficulty
Easy
Juniper
Business
Use Only
Objectives
experimenting with existing Python code;
discovering and fixing basic syntax errors;
becoming familiar with the print() function and its formatting capabilities.
Scenario
We strongly encourage you to play with the code we've written for you, and make some
(maybe even destructive) amendments. Feel free to modify any part of the code, but there is
one condition - learn from your mistakes and draw your own conclusions.
Try to:
minimize the number of print() function invocations by inserting the \n sequence
into the strings
make the arrow twice as large (but keep the proportions)
duplicate the arrow, placing both arrows side by side; note: a string may be
multiplied by using the following trick: "string" * 2 will
produce "stringstring" (we'll tell you more about it soon)
remove any of the quotes, and look carefully at Python's response; pay attention to
where Python sees an error - is this the place where the error really exists?
do the same with some of the parentheses;
change any of the print words into something else, differing only in case
(e.g., Print ) - what happens now?
replace some of the quotes with apostrophes; watch what happens carefully.
LAB
Estimated time
5-15 minutes
Level of difficulty
Easy
Objectives
experimenting with existing Python code;
discovering and fixing basic syntax errors;
becoming familiar with the print() function and its formatting capabilities.
Scenario
We strongly encourage you to play with the code we've written for you, and make some
(maybe even destructive) amendments. Feel free to modify any part of the code, but there is
one condition - learn from your mistakes and draw your own conclusions.
Juniper
Business
Use Only
Try to:
minimize the number of print() function invocations by inserting the \n sequence
into the strings
make the arrow twice as large (but keep the proportions)
duplicate the arrow, placing both arrows side by side; note: a string may be
multiplied by using the following trick: "string" * 2 will
produce "stringstring" (we'll tell you more about it soon)
remove any of the quotes, and look carefully at Python's response; pay attention to
where Python sees an error - is this the place where the error really exists?
do the same with some of the parentheses;
change any of the print words into something else, differing only in case
(e.g., Print ) - what happens now?
replace some of the quotes with apostrophes; watch what happens carefully.
Console
* *
* * * *
* * * *
* * * *
*** *** *** ***
* * * *
* * * *
***** *****
Key takeaways
1. The print() function is a built-in function. It prints/outputs a specified message to the
screen/consol window.
2. Built-in functions, contrary to user-defined functions, are always available and don't have
to be imported. Python 3.8 comes with 69 built-in functions. You can find their full list
provided in alphabetical order in the Python Standard Library.
Juniper
Business
Use Only
comma, e.g., print("Hello,", "world!") . An "empty" print() function outputs an
empty line to the screen.
4. Python strings are delimited with quotes, e.g., "I am a string" (double quotes), or 'I
am a string, too' (single quotes).
6. In Python strings the backslash ( \ ) is a special character which announces that the next
character has a different meaning, e.g., \n (the newline character) starts a new output line.
7. Positional arguments are the ones whose meaning is dictated by their position, e.g., the
second argument is outputted after the first, the third is outputted after the second, etc.
8. Keyword arguments are the ones whose meaning is not dictated by their location, but
by a special word (keyword) used to identify them.
9. The end and sep parameters can be used for formatting the output of
the print() function. The sep parameter specifies the separator between the outputted
arguments (e.g., print("H", "E", "L", "L", "O", sep="-") , whereas
the end parameter specifies what to print at the end of the print statement.
123
Can you guess what value it represents? Of course you can - it's one hundred twenty three.
Does it represent any value? Maybe. It can be the symbol of the speed of light, for example. It also can be
the constant of integration. Or even the length of a hypotenuse in the sense of a Pythagorean theorem.
There are many possibilities.
Juniper
Business
Use Only
You cannot choose the right one without some additional knowledge.
And this is the clue: 123 is a literal, and c is not.
You use literals to encode data and to put them into your code. We're now going to show you some
conventions you have to obey when using Python.
The first line looks familiar. The second seems to be erroneous due to the visible lack of
quotes.
If everything went okay, you should now see two identical lines.
The print() function presents them in exactly the same way - this example is obvious, as
their human-readable representation is also the same. Internally, in the computer's
memory, these two values are stored in completely different ways - the string exists as just a
string - a series of letters.
The number is converted into machine representation (a set of bits). The print() function
is able to show them both in a form readable to humans.
We're now going to be spending some time discussing numeric literals and their internal
life.
Integers
You may already know a little about how computers perform calculations on numbers. Perhaps you've
heard of the binary system, and know that it's the system computers use for storing numbers, and that they
can perform any operation upon them.
Juniper
Business
Use Only
We won't explore the intricacies of positional numeral systems here, but we'll say that the numbers handled
by modern computers are of two types:
integers, that is, those which are devoid of the fractional part;
and floating-point numbers (or simply floats), that contain (or are able to contain) the fractional
part.
This definition is not entirely accurate, but quite sufficient for now. The distinction is very important, and
the boundary between these two types of numbers is very strict. Both of these kinds of numbers differ
significantly in how they're stored in a computer memory and in the range of acceptable values.
The characteristic of the numeric value which determines its kind, range, and application, is called
the type.
If you encode a literal and place it inside Python code, the form of the literal determines the representation
(type) Python will use to store it in the memory.
For now, let's leave the floating-point numbers aside (we'll come back to them soon) and consider the
question of how Python recognizes integers.
The process is almost like how you would write them with a pencil on paper - it's simply a string of digits
that make up the number. But there's a reservation - you must not interject any characters that are not digits
inside the number.
Take, for example, the number eleven million one hundred and eleven thousand one hundred and eleven. If
you took a pencil in your hand right now, you would write the number like this: 11,111,111 , or like
this: 11.111.111 , or even like this: 11 111 111 .
It's clear that this provision makes it easier to read, especially when the number consists of many digits.
However, Python doesn't accept things like these. It's prohibited. What Python does allow, though, is the
use of underscores in numeric literals.*
Therefore, you can write this number either like this: 11111111 , or like that: 11_111_111 .
NOTE *Python 3.6 has introduced underscores in numeric literals, allowing for placing single
underscores between digits and after base specifiers for improved readability. This feature is not available
in older versions of Python.
And how do we code negative numbers in Python? As usual - by adding a minus. You can write: -
11111111 , or -11_111_111 .
Positive numbers do not need to be preceded by the plus sign, but it's permissible, if you wish to do it. The
following lines describe the same number: +11111111 and 11111111 .
Juniper
Business
Use Only
There are two additional conventions in Python that are unknown to the world of mathematics. The first
allows us to use numbers in an octal representation.
If an integer number is preceded by an 0O or 0o prefix (zero-o), it will be treated as an octal value. This
means that the number must contain digits taken from the [0..7] range only.
print (0o123)
The second convention allows us to use hexadecimal numbers. Such numbers should be preceded by the
prefix 0x or 0X (zero-x).
0x123 is a hexadecimal number with a (decimal) value equal to 291 . The print() function can manage
these values too. Try this:
print (0x123)
Floats
Now it's time to talk about another type, which is designed to represent and to store the numbers that (as a
mathematician would say) have a non-empty decimal fraction.
They are the numbers that have (or may have) a fractional part after the decimal point, and although such a
definition is very poor, it's certainly sufficient for what we wish to discuss.
Whenever we use a term like two and a half or minus zero point four, we think of numbers which the
computer considers floating-point numbers:
2.5
-0.4
Note: two and a half looks normal when you write it in a program, although if your native language prefers
to use a comma instead of a point in the number, you should ensure that your number doesn't contain
any commas at all.
Python will not accept that, or (in very rare but possible cases) may misunderstand your intentions, as the
comma itself has its own reserved meaning in Python.
If you want to use just a value of two and a half, you should write it as shown above. Note once again -
there is a point between 2 and 5 - not a comma.
As you can probably imagine, the value of zero point four could be written in Python as:
Juniper
Business
Use Only
0.4
But don't forget this simple rule - you can omit zero when it is the only digit in front of or after the decimal
point.
.4
4.
4
4.0
You may think that they are exactly the same, but Python sees them in a completely different way.
On the other hand, it's not only points that make a float. You can also use the letter e .
When you want to use any numbers that are very large or very small, you can use scientific notation.
Take, for example, the speed of light, expressed in meters per second. Written directly it would look like
this: 300000000 .
To avoid writing out so many zeros, physics textbooks use an abbreviated form, which you have probably
already seen: 3 x 108 .
Juniper
Business
Use Only
In Python, the same effect is achieved in a slightly different way - take a look:
3E8
The letter E (you can also use the lower-case letter e - it comes from the word exponent) is a concise
record of the phrase times ten to the power of.
Note:
Coding floats
Let's see how this convention is used to record numbers that are very small (in the sense of their absolute
value, which is close to zero).
A physical constant called Planck's constant (and denoted as h), according to the textbooks, has the value
of: 6.62607 x 10-34.
If you would like to use it in a program, you should write it this way:
6.62607E-34
Note: the fact that you've chosen one of the possible forms of coding float values doesn't mean that Python
will present it the same way.
For example, let's say you've decided to use the following float literal:
0.0000000000000000000001
print (0.0000000000000000000001)
1e-22
output
Juniper
Business
Use Only
Python always chooses the more economical form of the number's presentation, and you should take
this into consideration when creating literals.
Strings
Strings are used when you need to process text (like names of all kinds, addresses, novels, etc.), not
numbers.
You already know a bit about them, e.g., that strings need quotes the way floats need points.
However, there is a catch. The catch is how to encode a quote inside a string which is already delimited by
quotes.
The first is based on the concept we already know of the escape character, which you should remember is
played by the backslash. The backslash can escape quotes too. A quote preceded by a backslash changes
its meaning - it's not a delimiter, but just a quote. This will work as intended:
Note: there are two escaped quotes inside the string - can you see them both?
The second solution may be a bit surprising. Python can use an apostrophe instead of a quote. Either of
these characters may delimit strings, but you must be consistent.
If you open a string with a quote, you have to close it with a quote.
If you start a string with an apostrophe, you have to end it with an apostrophe.
Juniper
Business
Use Only
Note: you don't need to do any escaping here.
Boolean values
To conclude with Python's literals, there are two additional ones.
They're not as obvious as any of the previous ones, as they're used to represent a very abstract value
- truthfulness.
Each time you ask Python if one number is greater than another, the question results in the creation of
some specific data - a Boolean value.
The name comes from George Boole (1815-1864), the author of the fundamental work, The Laws of
Thought, which contains the definition of Boolean algebra - a part of algebra which makes use of only
two distinct values: True and False , denoted as 1 and 0 .
A programmer writes a program, and the program asks questions. Python executes the program, and
provides the answers. The program must be able to react according to the received answers.
You'll never get a response like: I don't know or Probably yes, but I don't know for sure.
True
False
You cannot change anything - you have to take these symbols as they are, including case-sensitivity.
Juniper
Business
Use Only
Run the code in the Sandbox to check. Can you explain the result?
Estimated time
5-10 minutes
Level of difficulty
Easy
Objectives
becoming familiar with the print() function and its formatting capabilities;
practicing coding strings;
experimenting with Python code.
Scenario
Write a one-line piece of code, using the print() function, as well as the newline and
escape characters, to match the expected result outputted on three lines.
Expected output
"I'm"
""learning""
"""Python"""
print('"I\'m"','\n','"learning"','\n','\"\"\"python\"\"\"')
"I'm"
"learning"
"""python"""
Key takeaways
1. Literals are notations for representing some fixed values in code. Python has various types of literals -
for example, a literal can be a number (numeric literals, e.g., 123 ), or a string (string literals, e.g., "I am a
literal.").
2. The binary system is a system of numbers that employs 2 as the base. Therefore, a binary number is
made up of 0s and 1s only, e.g., 1010 is 10 in decimal.
Juniper
Business
Use Only
3. Integers (or simply ints) are one of the numerical types supported by Python. They are numbers written
without a fractional component, e.g., 256 , or -1 (negative integers).
4. Floating-point numbers (or simply floats) are another one of the numerical types supported by Python.
They are numbers that contain (or are able to contain) a fractional component, e.g., 1.27 .
5. To encode an apostrophe or a quote inside a string you can either use the escape character, e.g., 'I\'m
happy.' , or open and close the string using an opposite set of symbols to the ones you wish to encode,
e.g., "I'm happy." to encode an apostrophe, and 'He said "Python", not "typhoon"' to
encode a (double) quote.
6. Boolean values are the two constant objects True and False used to represent truth values (in
numeric contexts 1 is True , while 0 is False .
EXTRA
There is one more, special literal that is used in Python: the None literal. This literal is a so-
called NoneType object, and it is used to represent the absence of a value. We'll tell you more about it
soon.
Exercise 1
Exercise 2
The first is a string, the second is a numerical literal (a float), the third is a numerical literal (an integer),
and the fourth is a boolean literal.
Exercise 3
Juniper
Business
Use Only
1011
Check
Python as a calculator
Now, we're going to show you a completely new side of the print() function. You already
know that the function is able to show you the values of the literals passed to it by
arguments.
print (2+2)
Retype the code in the editor and run it. Can you guess the output?
You should see the number four. Feel free to experiment with other operators.
Without taking this too seriously, you've just discovered that Python can be used as a
calculator. Not a very handy one, and definitely not a pocket one, but a calculator
nonetheless.
Basic operators
An operator is a symbol of the programming language, which is able to operate on the
values.
For example, just as in arithmetic, the + (plus) sign is the operator which is able to add two
numbers, giving the result of the addition.
Not all Python operators are as obvious as the plus sign, though, so let's go through some of
the operators available in Python, and we'll explain which rules govern their use, and how to
interpret the operations they perform.
We'll begin with the operators which are associated with the most widely recognizable
arithmetic operations:
Juniper
Business
Use Only
+ , - , * , / , // , % , **
The order of their appearance is not accidental. We'll talk more about it once we've gone
through them all.
Remember: Data and operators when connected together form expressions. The simplest
expression is a literal itself.
print("2"+2)
print("2"*2)
22
print("2"**2)
Classical mathematics prefers notation with superscripts, just like this: 23. Pure text editors
don't accept that, so Python uses ** instead, e.g., 2 ** 3 .
Note: we've surrounded the double asterisks with spaces in our examples. It's not
compulsory, but it improves the readability of the code.
The examples show a very important feature of virtually all Python numerical operators.
Juniper
Business
Use Only
Run the code and look carefully at the results it produces. Can you see any regularity here?
Remember: It's possible to formulate the following rules based on this result:
print(2 ** 3)
print(2 ** 3.)
print(2. ** 3)
print(2. ** 3.)
8
8.0
8.0
8.0
Run the code below and check if our integer vs. float rule is still working.
print (2 * 3)
print (2 * 3.)
print (2. * 3)
print (2. * 3.)
6
6.0
6.0
6.0
The value in front of the slash is a dividend, the value behind the slash, a divisor.
Juniper
Business
Use Only
Run the code below and analyze the results.
print (6 / 3)
print (6 / 3.)
print (6. / 3)
print (6. / 3.)
2.0
2.0
2.0
2.0
The result produced by the division operator is always a float, regardless of whether or
not the result seems to be a float at first glance: 1 / 2 , or if it looks like a pure integer: 2 /
1.
Is this a problem? Yes, it is. It happens sometimes that you really need a division that
provides an integer value, not a float.
its result lacks the fractional part - it's absent (for integers), or is always equal to zero
(for floats); this means that the results are always rounded;
it conforms to the integer vs. float rule.
print (6 // 3)
print (6 // 3.)
print (6. // 3)
print (6. // 3.)
Juniper
Business
Use Only
As you can see, integer by integer division gives an integer result. All other cases produce
floats.
print (6 // 4)
print (6. // 4)
Imagine that we used / instead of // - could you predict the results?
The result of integer division is always rounded to the nearest integer value that is less than
the real (not rounded) result.
Look at the code below and try to predict the results once again:
print (-6 // 4)
print (6. // -4)
Note: some of the values are negative. This will obviously affect the result. But how?
Juniper
Business
Use Only
The result is two negative twos. The real (not rounded) result is -1.5 in both cases.
However, the results are the subjects of rounding. The rounding goes toward the lesser
integer value, and the lesser integer value is -2 , hence: -2 and -2.0 .
NOTE
Integer division can also be called floor division. You will definitely come across this term in
the future.
print(6 // 4)
print(6. // 4)
print(-6 // 4)
print(6. // -4)
1
1.0
-2
-2.0
Its graphical representation in Python is the % (percent) sign, which may look a bit confusing.
Try to think of it as of a slash (division operator) accompanied by two funny little circles.
The result of the operator is a remainder left after the integer division.
In other words, it's the value left over after dividing one value by another to produce an
integer quotient.
Take a look at the snippet - try to predict its result and then run it:
print (14 % 4)
Juniper
Business
Use Only
This example is somewhat more complicated:
Check
Do not try to:
Operators: addition
The addition operator is the + (plus) sign, which is fully in line with mathematical standards.
print (-4 + 4)
print (-4. + 8)
The result should be nothing surprising. Run the code to check it.
Juniper
Business
Use Only
The subtraction operator is obviously the - (minus) sign, although you should note that
this operator also has another meaning - it can change the sign of a number.
For this reason, the subtraction operator is considered to be one of the binary operators,
just like the addition, multiplication and division operators.
But the minus operator may be used in a different (unary) way - take a look at the last line of
the snippet below:
print(-4 - 4)
print(4. - 8)
print(-1.1)
By the way: there is also a unary + operator. You can use it like this:
print (+2)
The operator preserves the sign of its only argument - the right one.
Although such a construction is syntactically correct, using it doesn't make much sense, and
it would be hard to find a good rationale for doing so.
Take a look at the snippet above - can you guess its output?
print(-4 - 4)
print(4. - 8)
print(-1.1)
print(+2)
-8
-4.0
-1.1
2
Juniper
Business
Use Only
So far, we've treated each operator as if it had no connection with the others. Obviously, such an ideal and
simple situation is a rarity in real programming.
Also, you will very often find more than one operator in one expression, and then this presumption is no
longer so obvious.
2 + 3 * 5
You surely remember that you should first multiply 3 by 5 and, keeping the 15 in your memory, then add it
to 2, thus getting the result of 17.
The phenomenon that causes some operators to act before others is known as the hierarchy of priorities.
Python precisely defines the priorities of all operators, and assumes that operators of a larger (higher)
priority perform their operations before the operators of a lower priority.
So, if you know that * has a higher priority than + , the computation of the final result should be obvious.
Most of Python's operators have left-sided binding, which means that the calculation of the expression is
conducted from left to right.
This simple example will show you how it works. Take a look:
print (9 % 6 % 2)
The result should be 1 . This operator has left-sided binding. But there's one interesting exception.
Juniper
Business
Use Only
Operators and their bindings: exponentiation
Repeat the experiment, but now with exponentiation.
print (2 ** 2 ** 3)
2 ** 2 → 4 ; 4 ** 3 → 64
2 ** 3 → 8 ; 2 ** 8 → 256
The result clearly shows that the exponentiation operator uses right-sided binding.
List of priorities
Since you're new to Python operators, we don't want to present the complete list of operator priorities right
now.
Instead, we'll show you its truncated form, and we'll expand it consistently as we introduce new operators.
Priority Operator
1 + , - unary
2 **
3 * , / , // , %
4 + , - binary
Note: we've enumerated the operators in order from the highest (1) to the lowest (4) priorities.
Juniper
Business
Use Only
Try to work through the following expression:
print (2 * 3 % 5)
Both operators ( * and % ) have the same priority, so the result can be guessed only when you know the
binding direction. How do you think? What is the result?
Check
In accordance with the arithmetic rules, subexpressions in parentheses are always calculated first.
You can use as many parentheses as you need, and they're often used to improve the readability of an
expression, even if they don't change the order of the operations.
Try to compute the value that's printed to the console. What's the result of the print() function?
Check
10.0
Key takeaways
1. An expression is a combination of values (or variables, operators, calls to functions - you will learn
about them soon) which evaluates to a value, e.g., 1 + 2 .
2. Operators are special symbols or keywords which are able to operate on the values and perform
(mathematical) operations, e.g., the * operator multiplies two values: x * y .
Juniper
Business
Use Only
3. Arithmetic operators in Python: + (addition), - (subtraction), * (multiplication), / (classic division -
always returns a float), % (modulus - divides left operand by right operand and returns the remainder of the
operation, e.g., 5 % 2 = 1 ), ** (exponentiation - left operand raised to the power of right operand,
e.g., 2 ** 3 = 2 * 2 * 2 = 8 ), // (floor/integer division - returns a number resulting from
division, but rounded down to the nearest whole number, e.g., 3 // 2.0 = 1.0 )
Exercise 1
Check
16 8.0 8
Exercise 2
Check
-0.5 0.5 0 -1
Juniper
Business
Use Only
Exercise 3
Check
-2 2 512
You already know that you can do some arithmetic operations with these numbers: add, subtract, etc.
You'll be doing that many times.
But it's quite a normal question to ask how to store the results of these operations, in order to use them in
other operations, and so on.
How do you save the intermediate results, and use them again to produce subsequent ones?
Python will help you with that. It offers special "boxes" (containers) for that purpose, and these boxes are
called variables - the name itself suggests that the content of these containers can be varied in (almost) any
way.
a name;
a value (the content of the container)
Variables do not appear in a program automatically. As developer, you must decide how many and which
variables to use in your programs.
If you want to give a name to a variable, you must follow some strict rules:
Juniper
Business
Use Only
upper- and lower-case letters are treated as different (a little differently than in the
real world - Alice and ALICE are the same first names, but in Python they are two
different variable names, and consequently, two different variables);
the name of the variable must not be any of Python's reserved words (the keywords
- we'll explain more about this soon).
Python does not impose restrictions on the length of variable names, but that doesn't mean that a long
variable name is always better than a short one.
Here are some correct, but not always convenient variable names:
Moreover, Python lets you use not only Latin letters but also characters specific to languages that use other
alphabets.
10t (does not begin with a letter), Exchange Rate (contains a space)
NOTE
The PEP 8 -- Style Guide for Python Code recommends the following naming convention for variables and
functions in Python:
variable names should be lowercase, with words separated by underscores to improve readability
(e.g., var , my_variable )
function names follow the same convention as variable names (e.g., fun , my_function )
it's also possible to use mixed case (e.g., myVariable ), but only in contexts where that's already
the prevailing style, to retain backwards compatibility with the adopted convention.
Keywords
Juniper
Business
Use Only
Take a look at the list of words that play a very special role in every Python program.
They are called keywords or (more precisely) reserved keywords. They are reserved because you
mustn't use them as names: neither for your variables, nor functions, nor any other named entities you
want to create.
The meaning of the reserved word is predefined, and mustn't be changed in any way.
Fortunately, due to the fact that Python is case-sensitive, you can modify any of these words by changing
the case of any letter, thus creating a new word, which is not reserved anymore.
import
You mustn't have a variable named in such a way - it is prohibited. But you can do this instead:
Import
These words might be a mystery to you now, but you'll soon learn the meaning of them.
Creating variables
What can you put inside a variable?
Anything.
You can use a variable to store any value of any of the already presented kinds, and many
more of the ones we haven't shown you yet.
The value of a variable is what you have put into it. It can vary as often as you need or want.
It can be an integer one moment, and a float a moment later, eventually becoming a string.
Let's talk now about two important things - how variables are created, and how to put
values inside them (or rather - how to give or pass values to them).
REMEMBER
A variable comes into existence as a result of assigning a value to it. Unlike in other
languages, you don't need to declare it in any special way.
Juniper
Business
Use Only
If you assign any value to a nonexistent variable, the variable will be automatically
created. You don't need to do anything else.
The creation (or otherwise - its syntax) is extremely simple: just use the name of the
desired variable, then the equal sign (=) and the value you want to put into the
variable.
var = 1
print (var)
The first of them creates a variable named var , and assigns a literal with an integer
value equal to 1 .
The second prints the value of the newly created variable to the console.
Note: print() has yet another side to it - it can handle variables too. Do you know what the
output of the snippet will be?
Check
Using variables
You're allowed to use as many variable declarations as you need to achieve your goal, like this:
var = 1
account_balance = 1000.0
client_name = 'John Doe'
print (var, account_balance, client_name)
print (var)
You're not allowed to use a variable which doesn't exist (in other words, a variable that was not assigned
a value).
Juniper
Business
Use Only
var = 1
print(Var)
We've tried to use a variable named Var , which doesn't have any value (note: var and Var are different
entities, and have nothing in common as far as Python's concerned).
REMEMBER
You can use the print() function and combine text and variables using the + operator to output strings
and variables, e.g.:
var = "3.8.5"
print("Python version: " + var)
Check
The equal sign is in fact an assignment operator. Although this may sound strange, the operator has a
simple syntax and unambiguous interpretation.
It assigns the value of its right argument to the left, while the right argument may be an arbitrarily complex
expression involving literals, operators and already defined variables.
var = 1
print (var)
var = var + 1
print (var)
Juniper
Business
Use Only
The code sends two lines to the console:
1
2
output
The first line of the snippet creates a new variable named var and assigns 1 to it.
The statement reads: assign a value of 1 to a variable named var .
The third line assigns the same variable with the new value taken from the variable itself, summed
with 1 . Seeing a record like that, a mathematician would probably protest - no value may be equal to itself
plus one. This is a contradiction. But Python treats the sign = not as equal to, but as assign a value.
Take the current value of the variable var , add 1 to it and store the result in the variable var .
In effect, the value of variable var has been incremented by one, which has nothing to do with
comparing the variable with any value.
Do you know what the output of the following snippet will be?
var = 100
var = 200 + 300
print (var)
Check
500 - why? Well, first, the var variable is created and assigned a value of 100. Then, the same variable is
assigned a new value: the result of adding 200 to 300, which is 500.
Juniper
Business
Use Only
Now you should be able to construct a short program solving simple mathematical
problems such as the Pythagorean theorem:
The square of the hypotenuse is equal to the sum of the squares of the other two sides.
The following code evaluates the length of the hypotenuse (i.e., the longest side of a right-
angled triangle, the one opposite of the right angle) using the Pythagorean theorem:
a = 3.0
b = 4.0
c = (a ** 2 + b ** 2) ** 0.5
print ("c =", c)
Note: we need to make use of the ** operator to evaluate the square root as:
√ (x) = x(½)
and
c = √ a2 + b2
Can you guess the output of the code?
Check below and run the code in the editor to confirm your predictions.
Check
c = 5.0
Estimated time
10 minutes
Level of difficulty
Easy
Objectives
becoming familiar with the concept of storing and working with different data types
in Python;
experimenting with Python code.
Juniper
Business
Use Only
Scenario
Here is a short story:
Once upon a time in Appleland, John had three apples, Mary had five apples, and Adam had
six apples. They were all very happy and lived for a long time. End of story.
Shortcut operators
It's time for the next set of operators that make a developer's life easier.
Very often, we want to use one and the same variable both to the right and left sides of the = operator.
For example, if we need to calculate a series of successive values of powers of 2, we may use a piece like
this:
x = x * 2
Juniper
Business
Use Only
You may use an expression like this if you can't fall asleep and you're trying to deal with it using some
good, old-fashioned methods:
sheep = sheep + 1
Python offers you a shortened way of writing operations like these, which can be coded as follows:
x *= 2
sheep += 1
If op is a two-argument operator (this is a very important condition) and the operator is used in the
following context:
Take a look at the examples below. Make sure you understand them all.
i = i + 2 * j ⇒ i += 2 * j
x = x ** 2 ⇒ x **= 2
LAB
Estimated time
10 minutes
Level of difficulty
Easy
Juniper
Business
Use Only
Objectives
becoming familiar with the concept of, and working with, variables;
performing basic computations and conversions;
experimenting with Python code.
Scenario
Miles and kilometers are units of length or distance.
Bearing in mind that 1 mile is equal to approximately 1.61 kilometers, complete the
program in the editor so that it converts:
miles to kilometers;
kilometers to miles.
Do not change anything in the existing code. Write your code in the places indicated by ### .
Test your program with the data we've provided in the source code.
Pay particular attention to what is going on inside the print() function. Analyze how we
provide multiple arguments to the function, and how we output the expected data.
Note that some of the arguments inside the print() function are strings (e.g., "miles is" ,
whereas some other are variables (e.g., miles ).
TIP
There's one more interesting thing happening there. Can you see another function inside
the print() function? It's the round() function. Its job is to round the outputted result to
the number of decimal places specified in the parentheses, and return a float (inside
the round() function you can find the variable name, a comma, and the number of decimal
places we're aiming for). We're going to talk about functions very soon, so don't worry that
everything may not be fully clear yet. We just want to spark your curiosity.
After completing the lab, open Sandbox, and experiment more. Try to write different
converters, e.g., a USD to EUR converter, a temperature converter, etc. - let your imagination
fly! Try to output the results by combining strings and variables. Try to use and experiment
with the round() function to round your results to one, two, or three decimal places. Check
out what happens if you don't provide any number of digits. Remember to test your
programs.
Juniper
Business
Use Only
Expected output
7.38 miles is 11.88 kilometers
12.25 kilometers is 7.61 miles
kilometers = 12.25
miles = 7.38
miles_to_kilometers = miles * 1.61
kilometers_to_miles = kilometers / 1.61
print(miles, "miles is", round(miles_to_kilometers, 2), "kilometers")
print(kilometers, "kilometers is", round(kilometers_to_miles, 2),
"miles")
Console
7.38 miles is 11.88 kilometers
12.25 kilometers is 7.61 miles
LAB
Estimated time
10-15 minutes
Level of difficulty
Easy
Objectives
becoming familiar with the concept of numbers, operators, and arithmetic
operations in Python;
performing basic calculations.
Scenario
Take a look at the code in the editor: it reads a float value, puts it into a variable named x ,
and prints the value of a variable named y . Your task is to complete the code in order to
evaluate the following expression:
3x3 - 2x2 + 3x - 1
Juniper
Business
Use Only
Remember that classical algebraic notation likes to omit the multiplication operator - you
need to use it explicitly. Note how we change data type to make sure that x is of
type float .
Keep your code clean and readable, and test it using the data we've provided, each time
assigning it to the x variable (by hardcoding it). Don't be discouraged by any initial failures.
Be persistent and inquisitive.
Test Data
Sample input
x = 0
x = 1
x = -1
Expected Output
y = -1.0
y = 3.0
y = -9.0
output
x = -1
x = float(x)
y = 3*(x**3)-2*(x**2)+3*x-1
print("y =", y)
y = -1.0
y = 3.0
y = -9.0
Key takeaways
1. A variable is a named location reserved to store values in the memory. A variable is created or
initialized automatically when you assign a value to it for the first time. (2.1.4.1)
Juniper
Business
Use Only
2. Each variable must have a unique name - an identifier. A legal identifier name must be a non-empty
sequence of characters, must begin with the underscore( _ ), or a letter, and it cannot be a Python keyword.
The first character may be followed by underscores, letters, and digits. Identifiers in Python are case-
sensitive. (2.1.4.1)
4. You can also use compound assignment operators (shortcut operators) to modify values assigned to
variables, e.g., var += 1 , or var /= 5 * 2 . (2.1.4.8)
5. You can assign new values to already existing variables using the assignment operator or one of the
compound operators, e.g.: (2.1.4.5)
var = 2
print (var)
var = 3
print (var)
var += 1
print (var)
6. You can combine text and variables using the + operator, and use the print() function to output
strings and variables, e.g.: (2.1.4.4)
var = "007"
print ("Agent " + var)
Exercise 1
var = 2
var = 3
print (var)
Check
Juniper
Business
Use Only
Exercise 2
my_var
m
101
averylongvariablename
m101
m 101
Del
del
Check
my_var
averylongvariablename
m101
Del
Exercise 3
a = '1'
b = "1"
print (a + b)
Check
11
Juniper
Business
Use Only
Exercise 4
a = 6
b = 3
a /= 2 * b
print (a)
Check
1.0
2*b=6
a = 6 → 6 / 6 = 1.0
A remark inserted into the program, which is omitted at runtime, is called a comment.
How do you leave this kind of comment in the source code? It has to be done in a way that won't force
Python to interpret it as part of the code.
Whenever Python encounters a comment in your program, the comment is completely transparent to it -
from Python's point of view, this is only one space (regardless of how long the real comment is).
In Python, a comment is a piece of text that begins with a # (hash) sign and extends to the end of the line.
If you want a comment that spans several lines, you have to put a hash in front of them all.
Good, responsible developers describe each important piece of code, e.g., explaining the role of the
variables; although it must be stated that the best way of commenting variables is to name them in an
unambiguous manner.
Juniper
Business
Use Only
For example, if a particular variable is designed to store an area of some unique square, the
name square_area will obviously be better than aunt_jane .
Comments may be useful in another respect - you can use them to mark a piece of code that currently
isn't needed for whatever reason. Look at the example below, if you uncomment the highlighted line, this
will affect the output of the code:
This is often done during the testing of a program, in order to isolate the place where an error might be
hidden.
TIP
If you'd like to quickly comment or uncomment multiple lines of code, select the line(s) you wish to
modify and use the following keyboard shortcut: CTRL + / (Windows) or CMD + / (Mac OS). It's a very
useful trick, isn't it? Try this code in Sandbox.
Estimated time
5 minutes
Level of difficulty
Very Easy
Objectives
becoming familiar with the concept of comments in Python;
using and not using comments;
replacing comments with code;
experimenting with Python code.
Scenario
The code in the editor contains comments. Try to improve it: add or remove comments
where you find it appropriate (yes, sometimes removing a comment can make the code
Juniper
Business
Use Only
more readable), and change variable names where you think this will improve code
comprehension.
NOTE
Comments are very important. They are used not only to make your programs easier to
understand, but also to disable those pieces of code that are currently not
needed (e.g., when you need to test some parts of your code only, and ignore other). Good
programmers describe each important piece of code, and give self-commenting names to
variables, as sometimes it is simply much better to leave information in the code.
It's good to use readable variable names, and sometimes it's better to divide your
code into named pieces (e.g., functions). In some situations, it's a good idea to write the
steps of computations in a clearer way.
One more thing: it may happen that a comment contains a wrong or incorrect piece of
information - you should never do that on purpose!
a = 2 # number of hours
seconds = 3600 # number of seconds in 1 hour
#here we should also print "Goodbye", but a programmer didn't have time to write any code
#this is the end of the program that computes the number of seconds in 3 hour
Console
Hours: 2
Seconds in Hours: 7200
Key takeaways
1. Comments can be used to leave additional information in code. They are omitted at runtime. The
information left in source code is addressed to human readers. In Python, a comment is a piece of text that
begins with # . The comment extends to the end of line.
Juniper
Business
Use Only
2. If you want to place a comment that spans several lines, you need to place # in front of them all.
Moreover, you can use a comment to mark a piece of code that is not needed at the moment (see the last
line of the snippet below), e.g.:
3. Whenever possible and justified, you should give self-commenting names to variables, e.g., if you're
using two variables to store a length and width of something, the variable names length and width may
be a better choice than myvar1 and myvar2 .
4. It's important to use comments to make programs easier to understand, and to use readable and
meaningful variable names in code. However, it's equally important not to use variable names that are
confusing, or leave comments that contain wrong or incorrect information!
5. Comments can be important when you are reading your own code after some time (trust us, developers
do forget what their own code does), and when others are reading your code (can help them understand
what your programs do and how they do it more quickly).
Exercise 1
# print("String #1")
print("String #2")
Check
String #2
Exercise 2
# This is
a multiline
comment. #
Juniper
Business
Use Only
print("Hello!")
Check
The input() function
We're now going to introduce you to a completely new function, which seems to be a mirror reflection of
the good old print() function.
print() has no usable result. The meaning of the new function is to return a very usable result.
The function is named input() . The name of the function says everything.
The input() function is able to read data entered by the user and to return the same data to the running
program.
The program can manipulate the data, making the code truly interactive.
Virtually all programs read and process data. A program which doesn't get a user's input is a deaf
program.
Note:
The program prompts the user to input some data from the console (most likely using a
keyboard, although it is also possible to input data using voice or image);
the input() function is invoked without arguments (this is the simplest way of using the
function); the function will switch the console to input mode; you'll see a blinking cursor, and
you'll be able to input some keystrokes, finishing off by hitting the Enter key; all the inputted data
will be sent to your program through the function's result;
note: you need to assign the result to a variable; this is crucial - missing out this step will cause the
entered data to be lost;
Juniper
Business
Use Only
then we use the print() function to output the data we get, with some additional remarks.
Try to run the code and let the function show you what it can do for you.
Note:
the input() function is invoked with one argument - it's a string containing a message;
the message will be displayed on the console before the user is given an opportunity to enter
anything;
input() will then do its job.
This variant of the input() invocation simplifies the code and makes it clearer.
A string containing all the characters the user enters from the keyboard. It is not an integer or a float.
This means that you mustn't use it as an argument of any arithmetic operation, e.g., you can't use this
data to square it, divide it by anything, or divide anything by it.
Juniper
Business
Use Only
The input() function - prohibited operations
Look at the code in the editor. Run it, enter any number, and press Enter.
What happens?
output
The last line of the sentence explains everything - you tried to apply the ** operator
to 'str' (string) accompanied with 'float' .
This is prohibited.
This should be obvious - can you predict the value of "to be or not to be" raised to the
power of 2 ?
Have we fallen into a deadlock? Is there a solution to this issue? Of course there is.
Enter a number: 10
Traceback (most recent call last):
File "main.py", line 4, in <module>
something = anything ** 2.0
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'float'
Type casting
Juniper
Business
Use Only
Python offers two simple functions to specify a type of data and solve this problem - here
they are: int() and float() .
This is very simple and very effective. Moreover, you can invoke any of the functions by
passing the input() results directly to them. There's no need to use any variable as an
intermediate storage.
We've implemented the idea in the editor - take a look at the code.
Can you imagine how the string entered by the user flows from input() into print() ?
Try to run the modified code. Don't forget to enter a valid number.
Check some different values, small and big, negative and positive. Zero is a good input, too.
Enter a number: 10
10.0 to the power of 2 is 100.0
You'll eventually be able to write complete programs, accepting data in the form of numbers, processing
them and displaying the results.
Of course, these programs will be very primitive and not very usable, as they cannot make decisions, and
consequently are not able to react differently to different situations.
This is not really a problem, though; we'll show you how to overcome it soon.
Our next example refers to the earlier program to find the length of a hypotenuse. Let's rewrite it and make
it able to read the lengths of the legs from the console.
Juniper
Business
Use Only
Check out the editor window - this is how it looks now.
The program asks the user twice for both legs' lengths, evaluates the hypotenuse and prints the result.
Let's ignore this weakness for now. We'll come back to it soon.
Note that in the program that you can see in the editor, the hypo variable is used for only one purpose - to
save the calculated value between the execution of the adjoining line of code.
As the print() function accepts an expression as its argument, you can remove the variable from the
code.
Sandbox
Code
leg_a = float(input("Input first leg length: "))
leg_b = float(input("Input second leg length: "))
hypo = (leg_a**2 + leg_b**2) ** .5
print("Hypotenuse length is", hypo)
1
2
3
4
5
leg_a = float(input("Input first leg length: "))
leg_b = float(input("Input second leg length: "))
hypo = (leg_a**2 + leg_b**2) ** .5
print("Hypotenuse length is", hypo)
Console
Juniper
Business
Use Only
We want to show you that they have a second function. They are able to do something more
than just add and multiply.
We've seen them in action where their arguments are numbers (floats or integers, it doesn't
matter).
Now we're going to show you that they can handle strings, too, albeit in a very specific way.
Concatenation
The + (plus) sign, when applied to two strings, becomes a concatenation operator:
string + string
It simply concatenates (glues) two strings into one. Of course, like its arithmetic sibling, it
can be used more than once in one expression, and in such a context it behaves according
to left-sided binding.
Don't forget - if you want the + sign to be a concatenator, not an adder, you must ensure
that both its arguments are strings.
Note: using + to concatenate strings lets you construct the output in a more precise way
than with a pure print() function, even if enriched with the end= and sep= keyword
arguments.
Run the code and see if the output matches your predictions.
Juniper
Business
Use Only
lnam = input("May I have your last name, please? ")
print("Thank you.")
print("\nYour name is " + fnam + " " + lnam + ".",end="&",sep="--")
Replication
The * (asterisk) sign, when applied to a string and number (or a number and string, as it
remains commutative in this position) becomes a replication operator:
string * number
number * string
It replicates the string the same number of times specified by the number.
For example:
REMEMBER
This simple program "draws" a rectangle, making use of an old operator ( + ) in a new role:
Juniper
Business
Use Only
Note the way in which we've used the parentheses in the second line of the code.
+----------+
| |
| |
| |
| |
| |
+----------+
Type conversion: str()
You already know how to use the int() and float() functions to convert a string into a
number.
This type of conversion is not a one-way street. You can also convert a number into a
string, which is way easier and safer - this operation is always possible.
str (number)
To be honest, it can do much more than just transform numbers into strings, but that can
wait for later.
Juniper
Business
Use Only
We've modified it a bit to show you how the str() function works. Thanks to this, we
can pass the whole result to the print() function as one string, forgetting about the
commas.
You already know the basic data types, and a set of fundamental operators. You know how
to organize the output and how to get data from the user. These are very strong
foundations for Module 3. But before we move on to the next module, let's do a few labs,
and recap all that you've learned in this section.
Estimated time
5-10 minutes
Level of difficulty
Easy
Objectives
becoming familiar with the inputting and outputting of data in Python;
evaluating simple expressions.
Scenario
Your task is to complete the code in order to evaluate the results of four basic arithmetic
operations.
You may not be able to protect the code from a user who wants to divide by zero. That's
okay, don't worry about it for now.
We won't show you any test data - that would be too simple.
Juniper
Business
Use Only
x = int(input("Enter the 1st number: \t"))
y = int(input("Enter the 2nd number: \t"))
print(x+y)
print(x-y)
print(x*y)
print(x/y)
print(x**y)
print(x%y)
Estimated time
20 minutes
Level of difficulty
Intermediate
Objectives
becoming familiar with the concept of numbers, operators and arithmetic operations
in Python;
understanding the precedence and associativity of Python operators, as well as the
proper use of parentheses.
Scenario
Your task is to complete the code in order to evaluate the following expression:
Juniper
Business
Use Only
The result should be assigned to y . Be careful - watch the operators and keep their priorities
in mind. Don't hesitate to use as many parentheses as you need.
You can use additional variables to shorten the expression (but it's not necessary). Test your
code carefully.
Test Data
Sample input: 1
Expected output:
y = 0.6000000000000001
Sample input: 10
Expected output:
y = 0.09901951266867294
Expected output:
y = 0.009999000199950014
Juniper
Business
Use Only
Sample input: -5
Expected output:
y = -0.19258202567760344
Estimated time
15-20 minutes
Level of difficulty
Easy
Objectives
improving the ability to use numbers, operators, and arithmetic operations in
Python;
using the print() function's formatting capabilities;
learning to express everyday-life phenomena in terms of programming language.
Scenario
Your task is to prepare a simple code able to evaluate the end time of a period of time,
given as a number of minutes (it could be arbitrarily large). The start time is given as a pair
of hours (0..23) and minutes (0..59). The result has to be printed to the console.
For example, if an event starts at 12:17 and lasts 59 minutes, it will end at 13:16.
Don't worry about any imperfections in your code - it's okay if it accepts an invalid time - the
most important thing is that the code produce valid results for valid input data.
Test your code carefully. Hint: using the % operator may be the key to success.
Juniper
Business
Use Only
Test Data
Sample input:12
17
59
Sample input:23
58
642
Sample input:0
2939
dura_hr = dura // 60
dura_min = dura % 60
end_min = mins + dura_min
end_hour = hour+(end_min//60)
end_min %= 60
print(end_hour,":",end_min)
Juniper
Business
Use Only
Key takeaways
1. The print() function sends data to the console, while the input() function gets data
from the console.
2. The input() function comes with an optional parameter: the prompt string. It allows
you to write a message before the user input, e.g.:
3. When the input() function is called, the program's flow is stopped, the prompt symbol
keeps blinking (it prompts the user to take action when the console is switched to input
mode) until the user has entered an input and/or pressed the Enter key.
NOTE
You can test the functionality of the input() function in its full scope locally on your
machine. For resource optimization reasons, we have limited the maximum program
execution time in Edube to a few seconds. Go to Sandbox, copy-paste the above snippet,
run the program, and do nothing - just wait a few seconds to see what happens. Your
program should be stopped automatically after a short moment. Now open IDLE, and run
the same program there - can you see the difference?
Tip: the above-mentioned feature of the input() function can be used to prompt the user
to end a program. Look at the code below:
3. The result of the input() function is a string. You can add strings to each other using the
concatenation ( + ) operator. Check out this code:
Juniper
Business
Use Only
print (num_1 + num_2) # the program returns 1221
Exercise 1
Check
55
Exercise 2
Check
<class 'str'>
>>> 1/2+3//3+4**2
17.5
>>> 3//17
0
>>> 0.5+3//3+4**2
17.5
>>> 3.5//3
1.0
>>> 3.5//3+4**2
Juniper
Business
Use Only
17.0
>>> 3//3
1
>>>
1st division of ½ then floor divison of 3//3 and then root multiplication of 4 and 2
Then add all 3. Ans is 17.5
Python Essentials 1:
Module 3
Boolean Values, Conditional Execution, Loops, Lists and List Processing, Logical and
Bitwise Operations
A computer executes the program and provides the answers. The program must be able to react
according to the received answers.
You will never get a response like Let me think...., I don't know, or Probably yes, but I don't know for sure.
To ask questions, Python uses a set of very special operators. Let's go through them one after another,
illustrating their effects on some simple examples.
Juniper
Business
Use Only
Comparison: equality operator
Question: are two values equal?
It is a binary operator with left-sided binding. It needs two arguments and checks if they are equal.
Exercises
Now let's ask a few questions. Try to guess the answers.
2 == 2 Check
True - of course, 2 is equal to 2. Python will answer True (remember this pair of predefined
literals, True and False - they're Python keywords, too).
2 == 2. Check
This question is not as easy as the first one. Luckily, Python is able to convert the integer value into its real
equivalent, and consequently, the answer is True .
1 == 2 Check
This should be easy. The answer will be (or rather, always is) False .
Juniper
Business
Use Only
The == (equal to) operator compares the values of two operands. If they are equal, the
result of the comparison is True . If they are not equal, the result of the comparison
is False .
Look at the equality comparison below - what is the result of this operation?
var == 0
Note that we cannot find the answer if we do not know what value is currently stored in the
variable var .
If the variable has been changed many times during the execution of your program, or its
initial value is entered from the console, the answer to this question can be given only by
Python and only at runtime.
Now imagine a programmer who suffers from insomnia, and has to count black and white
sheep separately as long as there are exactly twice as many black sheep as white ones.
black_sheep == 2 * white_sheep
Due to the low priority of the == operator, the question shall be treated as equivalent to this
one:
black_sheep == (2 * white_sheep)
So, let's practice your understanding of the == operator now - can you guess the output of
the code below?
Juniper
Business
Use Only
Inequality: the not equal to operator (!=)
The != (not equal to) operator compares the values of two operands, too. Here is the
difference: if they are equal, the result of the comparison is False . If they are not equal, the
result of the comparison is True .
Now take a look at the inequality comparison below - can you guess the result of this
operation?
black_sheep = 4
white_sheep = 2
print(black_sheep == 2 * white_sheep)
True
If you want to know if there are more black sheep than white ones, you can write it as follows:
Juniper
Business
Use Only
Both of these operators (strict and non-strict), as well as the two others discussed in the next section,
are binary operators with left-sided binding, and their priority is greater than that shown
by == and != .
If we want to find out whether or not we have to wear a warm hat, we ask the following question:
We're going to check if there's a risk of being fined by the highway police (the first question is strict, the
second isn't).
There are at least two possibilities: first, you can memorize it (store it in a variable) and make use of it
later. How do you do that? Well, you would use an arbitrary variable like this:
The content of the variable will tell you the answer to the question asked.
The second possibility is more convenient and far more common: you can use the answer you get to make
a decision about the future of the program.
You need a special instruction for this purpose, and we'll discuss it very soon.
Now we need to update our priority table, and put all the new operators into it. It now looks as follows:
Juniper
Business
Use Only
Priority Operator
1 + , - unary
2 **
3 * , / , // , %
4 + , - binary
5 < , <= , > , >=
6 == , !=
Estimated time
5-10 minutes
Level of difficulty
Very Easy
Objectives
becoming familiar with the the input() function;
becoming familiar with comparison operators in Python.
Scenario
Using one of the comparison operators in Python, write a simple two-line program that
takes the parameter n as input, which is an integer, and prints False if n is less than 100 ,
and True if n is greater than or equal to 100 .
Don't create any if blocks (we're going to talk about them very soon). Test your code using
the data we've provided for you.
Test Data
Sample input: 55
Sample input: 99
Juniper
Business
Use Only
Sample input: 100
Sample input: -5
It's just like in real life: you do certain things or you don't when a specific condition is met or not, e.g., you
go for a walk if the weather is good, or stay home if it's wet and cold.
To make such decisions, Python offers a special instruction. Due to its nature and its application, it's called
a conditional instruction (or conditional statement).
There are several variants of it. We'll start with the simplest, increasing the difficulty slowly.
The first form of a conditional statement, which you can see below is written very informally but
figuratively:
if true_or_not:
do_this_if_true
This conditional statement consists of the following, strictly necessary, elements in this and this order only:
the if keyword;
Juniper
Business
Use Only
one or more white spaces;
an expression (a question or an answer) whose value will be interpreted solely in terms
of True (when its value is non-zero) and False (when it is equal to zero);
a colon followed by a newline;
an indented instruction or set of instructions (at least one instruction is absolutely required);
the indentation may be achieved in two ways - by inserting a particular number of spaces (the
recommendation is to use four spaces of indentation), or by using the tab character; note: if there
is more than one instruction in the indented part, the indentation should be the same in all lines;
even though it may look the same if you use tabs mixed with spaces, it's important to make all
indentations exactly the same - Python 3 does not allow mixing spaces and tabs for indentation.
If the true_or_not expression represents the truth (i.e., its value is not equal to zero), the
indented statement(s) will be executed;
if the true_or_not expression does not represent the truth (i.e., its value is equal to zero), the
indented statement(s) will be omitted (ignored), and the next executed instruction will be the
one after the original indentation level.
As you can see, having lunch is not a conditional activity and doesn't depend on the weather.
Knowing what conditions influence our behavior, and assuming that we have the parameterless
functions go_for_a_walk() and have_lunch() , we can write the following snippet:
if the_weather_is_good:
go_for_a_walk()
have_lunch()
if the_weather_is_good:
go_for_a_walk()
else:
go_to_a_theater()
Juniper
Business
Use Only
have_lunch()
If the weather is good, we'll go for a walk. Otherwise, we'll go to a theatre. No matter if the weather is
good or bad, we'll have lunch afterwards (after the walk or after going to the theatre).
Everything we've said about indentation works in the same manner inside the else branch:
if the_weather_is_good:
go_for_a_walk()
have_fun()
else:
go_to_a_theater()
enjoy_the_movie()
have_lunch()
Nested if-else statements
Now let's discuss two special cases of the conditional statement.
First, consider the case where the instruction placed after the if is another if .
Read what we have planned for this Sunday. If the weather is fine, we'll go for a walk. If we find a nice
restaurant, we'll have lunch there. Otherwise, we'll eat a sandwich. If the weather is poor, we'll go to the
theater. If there are no tickets, we'll go shopping in the nearest mall.
Let's write the same in Python. Consider carefully the code here:
if the_weather_is_good:
if nice_restaurant_is_found:
have_lunch()
else:
eat_a_sandwich()
else:
if tickets_are_available:
go_to_the_theater()
else:
go_shopping()
Juniper
Business
Use Only
this use of the if statement is known as nesting; remember that every else refers to
the if which lies at the same indentation level; you need to know this to determine how the ifs
and elses pair up;
consider how the indentation improves readability, and makes the code easier to understand and
trace.
The elif statement
The second special case introduces another new Python keyword: elif. As you probably suspect, it's a
shorter form of else if.
elif is used to check more than just one condition, and to stop when the first statement which is true is
found.
Our next example resembles nesting, but the similarities are very slight. Again, we'll change our plans and
express them as follows: If the weather is fine, we'll go for a walk, otherwise if we get tickets, we'll go to
the theater, otherwise if there are free tables at the restaurant, we'll go for lunch; if all else fails, we'll return
home and play chess.
Have you noticed how many times we've used the word otherwise? This is the stage where
the elif keyword plays its role.
if the_weather_is_good:
go_for_a_walk()
elif tickets_are_available:
go_to_the_theater()
elif table_is_available:
go_for_lunch()
else:
play_chess_at_home()
Notice again how the indentation improves the readability of the code.
This may sound a little puzzling, but hopefully some simple examples will help shed more light.
Juniper
Business
Use Only
Analyzing code samples
Now we're going to show you some simple yet complete programs. We won't explain them
in detail, because we consider the comments (and the variable names) inside the code to be
sufficient guides.
All the programs solve the same problem - they find the largest of several numbers and
print it out.
Example 1:
We'll start with the simplest case - how to identify the larger of two numbers:
The above snippet should be clear - it reads two integer values, compares them, and finds
which is the larger.
Example 2:
Now we're going to show you one intriguing fact. Python has an interesting feature, look at
the code below:
Juniper
Business
Use Only
Note: if any of the if-elif-else branches contains just one instruction, you may code it in a
more comprehensive form (you don't need to make an indented line after the keyword, but
just continue the line after the colon).
This style, however, may be misleading, and we're not going to use it in our future
programs, but it's definitely worth knowing if you want to read and understand someone
else's programs.
Example 3:
It's time to complicate the code - let's find the largest of three numbers. Will it enlarge the
code? A bit.
We assume that the first value is the largest. Then we verify this hypothesis with the two
remaining values.
Juniper
Business
Use Only
This method is significantly simpler than trying to find the largest number all at once, by
comparing all possible pairs of numbers (i.e., first with second, second with third, third with
first). Try to rebuild the code for yourself.
You already know the scheme, so extending the size of the problem will not be particularly complex.
But what happens if we ask you to write a program that finds the largest of two hundred numbers? Can you
imagine the code?
You'll need two hundred variables. If two hundred variables isn't bad enough, try to imagine searching for
the largest of a million numbers.
Imagine a code that contains 199 conditional statements and two hundred invocations of
the input() function. Luckily, you don't need to deal with that. There's a simpler approach.
We'll ignore the requirements of Python syntax for now, and try to analyze the problem without thinking
about the real programming. In other words, we'll try to write the algorithm, and when we're happy with
it, we'll implement it.
In this case, we'll use a kind of notation which is not an actual programming language (it can be neither
compiled nor executed), but it is formalized, concise and readable. It's called pseudocode.
largest_number = -999999999
number = int(input())
Juniper
Business
Use Only
if number == -1:
print(largest_number)
exit()
if number > largest_number:
largest_number = number
# Go to line 02
Firstly, we can simplify the program if, at the very beginning of the code, we assign the
variable largest_number with a value which will be smaller than any of the entered numbers. We'll
use -999999999 for that purpose.
Secondly, we assume that our algorithm will not know in advance how many numbers will be delivered to
the program. We expect that the user will enter as many numbers as she/he wants - the algorithm will work
well with one hundred and with one thousand numbers. How do we do that?
We make a deal with the user: when the value -1 is entered, it will be a sign that there are no more data
and the program should end its work.
Otherwise, if the entered value is not equal to -1 , the program will read another number, and so on.
The trick is based on the assumption that any part of the code can be performed more than once - precisely,
as many times as needed.
Performing a certain part of the code more than once is called a loop. The meaning of this term is probably
obvious to you.
Lines 02 through 08 make a loop. We'll pass through them as many times as needed to review all the
entered values.
Can you use a similar structure in a program written in Python? Yes, you can.
Extra Info
Python often comes with a lot of built-in functions that will do the work for you. For example, to find the
largest number of all, you can use a Python built-in function called max() . You can use it with multiple
arguments. Analyze the code below:
Juniper
Business
Use Only
number3 = int(input("Enter the third number: "))
By the same fashion, you can use the min() function to return the lowest number. You can rebuild the
above code and experiment with it in the Sandbox.
We're going to talk about these (and many other) functions soon. For the time being, our focus will be put
on conditional execution and loops to let you gain more confidence in programming and teach you the
skills that will let you fully understand and apply the two concepts in your code. So, for now, we're not
taking any shortcuts.
Estimated time
5-15 minutes
Level of difficulty
Easy
Objectives
becoming familiar with the the input() function;
becoming familiar with comparison operators in Python;
becoming familiar with the concept of conditional execution.
Scenario
Spathiphyllum, more commonly known as a peace lily or white sail plant, is one of the most
popular indoor houseplants that filters out harmful toxins from the air. Some of the toxins
that it neutralizes include benzene, formaldehyde, and ammonia.
Imagine that your computer program loves these plants. Whenever it receives an input in
the form of the word Spathiphyllum , it involuntarily shouts to the console the following
string: "Spathiphyllum is the best plant ever!"
Write a program that utilizes the concept of conditional execution, takes a string as input,
and:
Juniper
Business
Use Only
prints the sentence "Yes - Spathiphyllum is the best plant ever!" to the
screen if the inputted string is "Spathiphyllum" (upper-case)
prints "No, I want a big Spathiphyllum!" if the inputted string
is "spathiphyllum" (lower-case)
prints "Spathiphyllum! Not [input]!" otherwise. Note: [input] is the string
taken as input.
Test your code using the data we've provided for you. And get yourself a Spathiphyllum, too!
Test Data
Sample input: spathiphyllum
Estimated time
10-20 minutes
Juniper
Business
Use Only
Level of difficulty
Easy/Medium
Objectives
Familiarize the student with:
Scenario
Once upon a time there was a land - a land of milk and honey, inhabited by happy and
prosperous people. The people paid taxes, of course - their happiness had limits. The most
important tax, called the Personal Income Tax (PIT for short) had to be paid once a year, and
was evaluated using the following rule:
if the citizen's income was not higher than 85,528 thalers, the tax was equal to 18%
of the income minus 556 thalers and 2 cents (this was the so-called tax relief)
if the income was higher than this amount, the tax was equal to 14,839 thalers and 2
cents, plus 32% of the surplus over 85,528 thalers.
Note: this happy country never returns money to its citizens. If the calculated tax is less than
zero, it only means no tax at all (the tax is equal to zero). Take this into consideration during
your calculations.
Look at the code in the editor - it only reads one input value and outputs a result, so you
need to complete it with some smart calculations.
Test Data
Sample input: 10000
Juniper
Business
Use Only
Sample input: 100000
Estimated time
10-25 minutes
Level of difficulty
Easy/Medium
Objectives
Familiarize the student with:
using the if-elif-else statement;
Juniper
Business
Use Only
finding the proper implementation of verbally defined rules;
testing code using sample input and output.
Scenario
As you surely know, due to some astronomical reasons, years may be leap or common. The
former are 366 days long, while the latter are 365 days long.
Since the introduction of the Gregorian calendar (in 1582), the following rule is used to
determine the kind of year:
Look at the code in the editor - it only reads a year number, and needs to be completed with
the instructions implementing the test we've just described.
The code should output one of two possible messages, which are Leap year or Common
year , depending on the value entered.
It would be good to verify if the entered year falls into the Gregorian era, and output a
warning otherwise: Not within the Gregorian calendar period . Tip: use the !
= and % operators.
Test Data
Sample input: 2000
Juniper
Business
Use Only
Sample input: 1996
Key takeaways
1. The comparison (or the so-called relational) operators are used to compare values. The table below
illustrates how the comparison operators work, assuming that x = 0 , y = 1 , and z = 0 :
Juniper
Business
Use Only
x != y # True
x != z # False
!= returns True if operands' values are not equal, and False otherwise
x > y # False
True ifthe left operand's value is greater than the right operand's y > z # True
>
value, and False otherwise
x < y # True
True if the left operand's value is less than the right operand's value, y < z # False
<
and False otherwise
x >= y # False
x >= z # True
True if the left operand's value is greater than or equal to the right
≥ y >= z # True
operand's value, and False otherwise
x <= y # True
x <= z # True
True if
the left operand's value is less than or equal to the right
≤ y <= z # False
operand's value, and False otherwise
2. When you want to execute some code only if a certain condition is met, you can use a conditional
statement:
x = 10
if x == 10: # condition
print("x is equal to 10") # Executed if the condition is
True.
x = 10
Juniper
Business
Use Only
print("x is equal to 10") # Executed if condition three is
True.
x = 10
else :
print("x is greater than or equal to 10") # Executed if the
condition is False.
x = 10
if x > 5: # True
print("x > 5")
if x > 8: # True
print("x > 8")
else :
print("else will be executed")
Each if is tested separately. The body of else is executed if the last if is False .
Juniper
Business
Use Only
x = 10
if x == 10: # True
print("x == 10")
else :
print("else will not be executed")
If the condition for if is False , the program checks the conditions of the
subsequent elif blocks - the first elif block that is True is executed. If all the conditions
are False , the else block will be executed.
x = 10
if x > 5: # True
if x == 6: # False
print("nested: x == 6")
elif x == 10: # True
print("nested: x == 10")
else:
print("nested: else")
else :
print("else")
Exercise 1
Juniper
Business
Use Only
x = 5
y = 10
z = 8
print(x > y)
print(y > z)
Check
False
True
output
Exercise 2
x, y, z = 5, 10, 8
print(x > z)
print((y - 5) == x)
Check
False
True
output
Exercise 3
x, y, z = 5, 10, 8
x, y, z = z, y, x
print(x > z)
print((y - 5) == x)
Check
True
False
output
Juniper
Business
Use Only
Exercise 4
x = 10
if x == 10:
print(x == 10)
if x > 5:
print(x > 5)
if x < 10:
print(x < 10)
else:
print("else")
Check
True
True
else
output
Exercise 5
x = "1"
if x == 1:
print("one")
elif x == "1":
if int(x) > 1:
print("two")
elif int(x) < 1:
print("three")
else:
print("four")
if int(x) == 1:
print("five")
else:
print("six")
Juniper
Business
Use Only
Check
four
five
output
Exercise 6
x = 1
y = 1.0
z = "1"
if x == y:
print("one")
if y == int(z):
print("two")
elif x == y:
print("three")
else:
print("four")
Check
one
two
output
Note that this record also declares that if there is nothing to do, nothing at all will happen.
Juniper
Business
Use Only
while conditional_expression:
instruction
If you notice some similarities to the if instruction, that's quite all right. Indeed, the syntactic difference is
only one: you use the word while instead of the word if .
The semantic difference is more important: when the condition is met, if performs its statements only
once; while repeats the execution as long as the condition evaluates to True .
Note: all the rules regarding indentation are applicable here, too. We'll show you this soon.
while conditional_expression:
instruction_one
instruction_two
instruction_three
:
:
instruction_n
if you want to execute more than one statement inside one while , you must (as
with if ) indent all the instructions in the same way;
an instruction or set of instructions executed inside the while loop is called the loop's body;
if the condition is False (equal to zero) as early as when it is tested for the first time, the body is
not executed even once (note the analogy of not having to do anything if there is nothing to do);
the body should be able to change the condition's value, because if the condition is True at the
beginning, the body might run continuously to infinity - notice that doing a thing usually decreases
the number of things to do).
An infinite loop
An infinite loop, also called an endless loop, is a sequence of instructions in a program which repeat
indefinitely (loop endlessly.)
while True:
print("I'm stuck inside a loop.")
Juniper
Business
Use Only
This loop will infinitely print "I'm stuck inside a loop." on the screen.
NOTE
If you want to get the best learning experience from seeing how an infinite loop behaves, launch IDLE,
create a New File, copy-paste the above code, save your file, and run the program. What you will see is the
never-ending sequence of "I'm stuck inside a loop." strings printed to the Python console
window. To terminate your program, just press Ctrl-C (or Ctrl-Break on some computers). This will cause
the so-called KeyboardInterrupt exception and let your program get out of the loop. We'll talk about
it later in the course.
Let's go back to the sketch of the algorithm we showed you recently. We're going to show you how to use
this newly learned loop to find the largest number from a large set of entered data.
Analyze the program carefully. See where the loop starts (line 8). Locate the loop's body and find out how
the body is exited:
Check how this code implements the algorithm we showed you earlier.
Juniper
Business
Use Only
Let's look at another example employing the while loop. Follow the comments to find out
the idea and the solution.
odd_numbers = 0
even_numbers = 0
# 0 terminates execution.
while number != 0:
# Check if the number is odd.
if number % 2 == 1:
# Increase the odd_numbers counter.
odd_numbers += 1
else:
# Increase the even_numbers counter.
even_numbers += 1
# Read the next number.
number = int(input("Enter a number or type 0 to stop: "))
# Print results.
print ("Odd numbers count:", odd_numbers)
print ("Even numbers count:", even_numbers)
Try to recall how Python interprets the truth of a condition, and note that these two forms
are equivalent:
The condition that checks if a number is odd can be coded in these equivalent forms, too:
counter = 5
Juniper
Business
Use Only
while counter != 0:
print("Inside the loop.", counter)
counter -= 1
print ("Outside the loop.", counter)
This code is intended to print the string "Inside the loop." and the value stored in
the counter variable during a given loop exactly five times. Once the condition has not
been met (the counter variable has reached 0 ), the loop is exited, and the
message "Outside the loop." as well as the value stored in counter is printed.
But there's one thing that can be written more compactly - the condition of the while loop.
counter = 5
while counter:
print("Inside the loop.", counter)
counter -= 1
print ("Outside the loop.", counter)
REMEMBER
Don't feel obliged to code your programs in a way that is always the shortest and the most
compact. Readability may be a more important factor. Keep your code ready for a new
programmer.
Estimated time
15 minutes
Level of difficulty
Easy
Objectives
Familiarize the student with:
using the while loop;
Juniper
Business
Use Only
reflecting real-life situations in computer code.
Scenario
A junior magician has picked a secret number. He has hidden it in a variable
named secret_number . He wants everyone who run his program to play the Guess the
secret number game, and guess what number he has picked for them. Those who don't
guess the number will be stuck in an endless loop forever! Unfortunately, he does not know
how to complete the code.
Your task is to help the magician complete the code in the editor in such a way so that the
code:
EXTRA INFO
By the way, look at the print() function. The way we've used it here is called multi-line
printing. You can use triple quotes to print strings on multiple lines in order to make text
easier to read, or create a special text-based design. Experiment with it.
secret_number = 777
print(
"""
+================================+
| Welcome to my game, muggle! |
| Enter an integer number |
| and guess what number I've |
| picked for you. |
| So, what is the secret number? |
+================================+
""")
getNum = int(input("Guess my number"))
while getNum != 777:
print("Ha Ha! You're struck in my loop!")
Juniper
Business
Use Only
getNum = int(input("Guess my number"))
+================================+
| Welcome to my game, muggle! |
| Enter an integer number |
| and guess what number I've |
| picked for you. |
| So, what is the secret number? |
+================================+
Guess my number10
Ha Ha! You're struck in my loop!
Guess my number20
Ha Ha! You're struck in my loop!
Guess my number30
Ha Ha! You're struck in my loop!
Guess my number777
Imagine that a loop's body needs to be executed exactly one hundred times. If you would like to use
the while loop to do it, it may look like this:
i = 0
while i < 100:
# do_something()
i += 1
It would be nice if somebody could do this boring counting for you. Is that possible?
Of course it is - there's a special loop for these kinds of tasks, and it is named for .
Actually, the for loop is designed to do more complicated tasks - it can "browse" large collections of
data item by item. We'll show you how to do that soon, but right now we're going to present a simpler
variant of its application.
for i in range(100):
# do_something()
pass
Juniper
Business
Use Only
There are some new elements. Let us tell you about them:
the for keyword opens the for loop; note - there's no condition after it; you don't have to think
about conditions, as they're checked internally, without any intervention;
any variable after the for keyword is the control variable of the loop; it counts the loop's turns,
and does it automatically;
the in keyword introduces a syntax element describing the range of possible values being assigned
to the control variable;
the range() function (this is a very special function) is responsible for generating all the desired
values of the control variable; in our example, the function will create (we can even say that it
will feed the loop with) subsequent values from the following set: 0, 1, 2 .. 97, 98, 99; note: in this
case, the range() function starts its job from 0 and finishes it one step (one integer number)
before the value of its argument;
note the pass keyword inside the loop body - it does nothing at all; it's an empty instruction - we
put it here because the for loop's syntax demands at least one instruction inside the body (by the
way - if , elif , else and while express the same thing)
Our next examples will be a bit more modest in the number of loop repetitions.
Take a look at the snippet below. Can you predict its output?
for i in range(10):
print("The value of i is currently", i)
Note:
the loop has been executed ten times (it's the range() function's argument)
the last control variable's value is 9 (not 10 , as it starts from 0 , not from 1 )
The range() function invocation may be equipped with two arguments, not just one:
In this case, the first argument determines the initial (first) value of the control variable.
Juniper
Business
Use Only
The last argument shows the first value the control variable will not be assigned.
Note: the range() function accepts only integers as its arguments, and generates sequences of integers.
Can you guess the output of the program? Run it to check if you were right now, too.
The first value shown is 2 (taken from the range() 's first argument.)
The last is 7 (although the range() 's second argument is 8 ).
The third argument is an increment - it's a value added to control the variable at every loop
turn (as you may suspect, the default value of the increment is 1).
Can you tell us how many lines will appear in the console and what values they will contain?
You should be able to see the following lines in the console window:
output
Do you know why? The first argument passed to the range() function tells us what
the starting number of the sequence is (hence 2 in the output). The second argument tells
the function where to stop the sequence (the function generates numbers up to the
number indicated by the second argument, but does not include it). Finally, the third
argument indicates the step, which actually means the difference between each number in
the sequence of numbers generated by the function.
2 (starting number) → 5 ( 2 increment by 3 equals 5 - the number is within the range from 2
to 8) → 8 ( 5 increment by 3 equals 8 - the number is not within the range from 2 to 8,
because the stop parameter is not included in the sequence of numbers generated by the
function.)
Juniper
Business
Use Only
Note: if the set generated by the range() function is empty, the loop won't execute its body
at all.
Note: the set generated by the range() has to be sorted in ascending order. There's no
way to force the range() to create a set in a different form when the range() function
accepts exactly two arguments. This means that the range() 's second argument must be
greater than the first.
Let's have a look at a short program whose task is to write some of the first powers of two:
power = 1
for expo in range(16):
print("2 to the power of", expo, "is", power)
power *= 2
The expo variable is used as a control variable for the loop, and indicates the current value
of the exponent. The exponentiation itself is replaced by multiplying by two. Since 20 is equal
to 1, then 2 × 1 is equal to 21, 2 × 21 is equal to 22, and so on. What is the greatest exponent
for which our program still prints the result?
Run the code and check if the output matches your expectations.
Juniper
Business
Use Only
power = 1
for expo in range(16):
print("2 to the power of", expo, "is", power)
power *= 2
2 to the power of 0 is 1
2 to the power of 1 is 2
2 to the power of 2 is 4
2 to the power of 3 is 8
2 to the power of 4 is 16
2 to the power of 5 is 32
2 to the power of 6 is 64
2 to the power of 7 is 128
2 to the power of 8 is 256
2 to the power of 9 is 512
2 to the power of 10 is 1024
2 to the power of 11 is 2048
2 to the power of 12 is 4096
2 to the power of 13 is 8192
2 to the power of 14 is 16384
2 to the power of 15 is 32768
Level of difficulty
Very easy
Objectives
Familiarize the student with:
using the for loop;
reflecting real-life situations in computer code.
Scenario
Do you know what Mississippi is? Well, it's the name of one of the states and rivers in the
United States. The Mississippi River is about 2,340 miles long, which makes it the second
longest river in the United States (the longest being the Missouri River). It's so long that a
single drop of water needs 90 days to travel its entire length!
The word Mississippi is also used for a slightly different purpose: to count mississippily.
If you're not familiar with the phrase, we're here to explain to you what it means: it's used to
count seconds.
The idea behind it is that adding the word Mississippi to a number when counting seconds
aloud makes them sound closer to clock-time, and therefore "one Mississippi, two
Mississippi, three Mississippi" will take approximately an actual three seconds of time! It's
Juniper
Business
Use Only
often used by children playing hide-and-seek to make sure the seeker does an honest
count.
Your task is very simple here: write a program that uses a for loop to "count mississippily"
to five. Having counted to five, the program should print to the screen the final
message "Ready or not, here I come!"
EXTRA INFO
Note that the code in the editor contains two elements which may not be fully clear to you
at this moment: the import time statement, and the sleep() method. We're going to talk
about them soon.
For the time being, we'd just like you to know that we've imported the time module and
used the sleep() method to suspend the execution of each subsequent print() function
inside the for loop for one second, so that the message outputted to the console
resembles an actual counting. Don't worry - you'll soon learn more about modules and
methods.
Expected output
1 Mississippi
2 Mississippi
3 Mississippi
4 Mississippi
5 Mississippi
import time
for i in range(5):
print(i+1," Mississippi")
time.sleep(1)
print("Here I come")
1 Mississippi
2 Mississippi
3 Mississippi
4 Mississippi
5 Mississippi
Here I come
The break and continue statements
Juniper
Business
Use Only
So far, we've treated the body of the loop as an indivisible and inseparable sequence of
instructions that are performed completely at every turn of the loop. However, as
developer, you could be faced with the following choices:
it appears that it's unnecessary to continue the loop as a whole; you should refrain
from further execution of the loop's body and go further;
it appears that you need to start the next turn of the loop without completing the
execution of the current turn.
Python provides two special instructions for the implementation of both these tasks. Let's
say for the sake of accuracy that their existence in the language is not necessary - an
experienced programmer is able to code any algorithm without these instructions. Such
additions, which don't improve the language's expressive power, but only simplify the
developer's work, are sometimes called syntactic candy, or syntactic sugar.
break - exits the loop immediately, and unconditionally ends the loop's operation;
the program begins to execute the nearest instruction after the loop's body;
continue - behaves as if the program has suddenly reached the end of the body;
the next turn is started and the condition expression is tested immediately.
Now we'll show you two simple examples to illustrate how the two instructions work. Look
at the code in the editor. Run the program and analyze the output. Modify the code and
experiment.
# break - example
# continue - example
Juniper
Business
Use Only
Inside the loop. 1
Inside the loop. 2
Outside the loop.
Analyze the code, and judge whether and how you would use either of them.
largest_number = -99999999
counter = 0
while True:
number = int(input("Enter a number or type -1 to end program: "))
if number == -1:
break
counter += 1
if number > largest_number:
largest_number = number
if counter != 0:
print("The largest number is", largest_number)
else :
print("You haven't entered any number.")
largest_number = -99999999
counter = 0
Juniper
Business
Use Only
while number != -1:
if number == -1:
continue
counter += 1
if counter:
print("The largest number is", largest_number)
else :
print("You haven't entered any number.")
Look carefully, the user enters the first number before the program enters the while loop.
The subsequent number is entered when the program is already in the loop.
Again - run the program, test it, and experiment with it.
Analyze the code, and judge whether and how you would use either of them.
largest_number = -99999999
counter = 0
while True:
number = int(input("Enter a number or type -1 to end program: "))
if number == -1:
break
counter += 1
if number > largest_number:
largest_number = number
if counter != 0:
print("The largest number is", largest_number)
else :
print("You haven't entered any number.")
Juniper
Business
Use Only
Run it, test it, and experiment with it.
largest_number = -99999999
counter = 0
if counter:
print("The largest number is", largest_number)
else :
print("You haven't entered any number.")
Look carefully, the user enters the first number before the program enters the while loop.
The subsequent number is entered when the program is already in the loop.
Again - run the program, test it, and experiment with it.
largest_number = -99999999
counter = 0
number = 0
Juniper
Business
Use Only
if counter:
print("The largest number is", largest_number)
else:
print("You haven't entered any number.")
Estimated time
10-20 minutes
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
The break statement is used to exit/terminate a loop.
Design a program that uses a while loop and continuously asks the user to enter a word
unless the user enters "chupacabra" as the secret exit word, in which case the
message "You've successfully left the loop." should be printed to the screen, and
the loop should terminate.
Don't print any of the words entered by the user. Use the concept of conditional execution
and the break statement.
Juniper
Business
Use Only
wrd = ""
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
The continue statement is used to skip the current block and move ahead to the next
iteration, without executing the statements inside the loop.
Your task here is very special: you must design a vowel eater! Write a program that uses:
a for loop;
the concept of conditional execution (if-elif-else)
the continue statement.
Juniper
Business
Use Only
print the uneaten letters to the screen, each one of them on a separate line.
Test your program with the data we've provided for you.
Test data
Sample input: Gregory
Expected output:
G
R
G
R
Y
Expected output:
B
S
T
M
S
Expected output:
vowels = ['a','e','i','o','u','A','E','I','O','U']
user_word = input("Enter a string: ")
user_word = user_word.upper()
for letter in user_word:
if letter in vowels:
continue
print(letter)
Juniper
Business
Use Only
Estimated time
5-15 minutes
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Your task here is even more special than before: you must redesign the (ugly) vowel eater
from the previous lab (3.1.2.10) and create a better, upgraded (pretty) vowel eater! Write a
program that uses:
a for loop;
the concept of conditional execution (if-elif-else)
the continue statement.
Look at the code in the editor. We've created word_without_vowels and assigned an
empty string to it. Use concatenation operation to ask Python to combine selected letters
into a longer string during subsequent loop turns, and assign it to
the word_without_vowels variable.
Test your program with the data we've provided for you.
Juniper
Business
Use Only
Test data
Sample input: Gregory
Expected output:
GRGRY
Expected output:
BSTMS
Expected output:
word_without_vowels = ""
vowels = ['a','e','i','o','u','A','E','I','O','U']
user_word = input("Enter a string: ")
user_word = user_word.upper()
for letter in user_word:
if letter in vowels:
continue
word_without_vowels+=letter
print(word_without_vowels)
We'll show you how it works - try to judge for yourself if it's usable and whether you can live
without it or not.
In other words, try to convince yourself if the feature is valuable and useful, or is just
syntactic sugar.
Take a look at the snippet in the editor. There's something strange at the end -
the else keyword.
As you may have suspected, loops may have the else branch too, like if s.
Juniper
Business
Use Only
The loop's else branch is always executed once, regardless of whether the loop has
entered its body or not.
Can you guess the output? Run the program to check if you were right.
Modify the snippet a bit so that the loop has no chance to execute its body even once:
i = 5
while i < 5:
print(i)
i += 1
else :
print("else:", i)
The while 's condition is False at the beginning - can you see it?
Run and test the program, and check whether the else branch has been executed or not.
1
2
3
4
else: 5
i = 111
for i in range(2, 1):
print(i)
else :
print("else:", i)
Juniper
Business
Use Only
Can you guess the output?
The loop's body won't be executed here at all. Note: we've assigned the i variable before
the loop.
When the loop's body isn't executed, the control variable retains the value it had before the
loop.
Note: if the control variable doesn't exist before the loop starts, it won't exist when
the execution reaches the else branch.
Now we're going to tell you about some other kinds of variables. Our current variables can
only store one value at a time, but there are variables that can do much more - they
can store as many values as you want.
0
1
2
3
4
else: 4
Level of difficulty
Medium
Objectives
Familiarize the student with:
Scenario
Listen to this story: a boy and his father, a computer programmer, are playing with wooden
blocks. They are building a pyramid.
Juniper
Business
Use Only
Their pyramid is a bit weird, as it is actually a pyramid-shaped wall - it's flat. The pyramid is
stacked according to one simple principle: each lower layer contains one block more than
the layer above.
Your task is to write a program which reads the number of blocks the builders have, and
outputs the height of the pyramid that can be built using these blocks.
Note: the height is measured by the number of fully completed layers - if the builders
don't have a sufficient number of blocks and cannot complete the next layer, they finish
their work immediately.
Test Data
Sample input: 6
Sample input: 20
Juniper
Business
Use Only
Sample input: 1000
Sample input: 2
Level of difficulty
Medium
Objectives
Familiarize the student with:
Scenario
In 1937, a German mathematician named Lothar Collatz formulated an intriguing
hypothesis (it still remains unproven) which can be described in the following way:
1. take any non-negative and non-zero integer number and name it c0 ;
2. if it's even, evaluate a new c0 as c0 ÷ 2 ;
3. otherwise, if it's odd, evaluate a new c0 as 3 × c0 + 1 ;
4. if c0 ≠ 1 , skip to point 2.
The hypothesis says that regardless of the initial value of c0 , it will always go to 1.
Of course, it's an extremely complex task to use a computer in order to prove the
hypothesis for any natural number (it may even require artificial intelligence), but you can
use Python to check some individual numbers. Maybe you'll even find the one which would
disprove the hypothesis.
Write a program which reads one natural number and executes the above steps as long
as c0 remains different from 1. We also want you to count the steps needed to achieve the
goal. Your code should output all the intermediate values of c0 , too.
Juniper
Business
Use Only
Hint: the most important part of the problem is how to transform Collatz's idea into
a while loop - this is the key to success.
Test Data
Sample input: 15
Expected output:
46
23
70
35
106
53
160
80
40
20
10
5
16
8
4
2
1
steps = 17
Sample input: 16
Expected output:
8
4
2
1
steps = 4
Expected output:
3070
Juniper
Business
Use Only
1535
4606
2303
6910
3455
10366
5183
15550
7775
23326
11663
34990
17495
52486
26243
78730
39365
118096
59048
29524
14762
7381
22144
11072
5536
2768
1384
692
346
173
520
260
130
65
196
98
49
148
74
37
112
56
28
14
7
22
11
34
17
52
26
13
Juniper
Business
Use Only
40
20
10
5
16
8
4
2
1
steps = 62
Key takeaways
the while loop executes a statement or a set of statements as long as a specified boolean
condition is true, e.g.:
# Example 1
while True:
print("Stuck in an infinite loop.")
# Example 2
counter = 5
while counter > 2:
print(counter)
counter -= 1
the for loop executes a set of statements many times; it's used to iterate over a sequence (e.g., a
list, a dictionary, a tuple, or a set - you will learn about them soon) or other objects that are
iterable (e.g., strings). You can use the for loop to iterate over a sequence of numbers using the
built-in range function. Look at the examples below:
# Example 1
word = "Python"
for letter in word:
print(letter, end="*")
# Example 2
for i in range(1, 10):
if i % 2 == 0:
print(i)
Juniper
Business
Use Only
2. You can use the break and continue statements to change the flow of a loop:
You use continue to skip the current iteration, and continue with the next iteration, e.g.:
text = "pyxpyxpyx"
for letter in text:
if letter == "x":
continue
print(letter, end="")
3. The while and for loops can also have an else clause in Python. The else clause executes after
the loop finishes its execution as long as it has not been terminated by break , e.g.:
n = 0
while n != 3:
print(n)
n += 1
else :
print(n, "else")
print ()
Juniper
Business
Use Only
4. The range() function generates a sequence of numbers. It accepts integers and returns range objects.
The syntax of range() looks as follows: range(start, stop, step) , where:
start is an optional parameter specifying the starting number of the sequence (0 by default)
stop is an optional parameter specifying the end of the sequence generated (it is not included),
and step is an optional parameter specifying the difference between the numbers in the sequence
(1 by default.)
Example code:
for i in range(3):
print(i, end=" ") # Outputs: 0 1 2
Create a for loop that counts from 0 to 10, and prints odd numbers to the screen. Use the skeleton below:
Check
Sample solution:
for i in range(0, 11):
if i % 2 != 0:
print(i)
Exercise 2
Create a while loop that counts from 0 to 10, and prints odd numbers to the screen. Use the skeleton
below:
x = 1
while x < 11:
# Line of code.
Juniper
Business
Use Only
# Line of code.
# Line of code.
Check
Sample solution:
x = 1
if x % 2 != 0:
print(x)
x += 1
Exercise 3
Create a program with a for loop and a break statement. The program should iterate over characters in
an email address, exit the loop when it reaches the @ symbol, and print the part before @ on one line. Use
the skeleton below:
for ch in "[email protected]":
if ch == "@":
# Line of code.
# Line of code.
Check
Sample solution:
for ch in "[email protected]":
if ch == "@":
break
print(ch, end="")
Exercise 4
Juniper
Business
Use Only
Create a program with a for loop and a continue statement. The program should iterate over a string of
digits, replace each 0 with x , and print the modified string to the screen. Use the skeleton below:
Check
Sample solution:
for digit in "0165031806510":
if digit == "0":
print("x", end="")
continue
print(digit, end="")
Exercise 5
n = 3
while n > 0:
print(n + 1)
n -= 1
else:
print(n)
Check
Juniper
Business
Use Only
0
Exercise 6
n = range(4)
for num in n:
print(num - 1)
else:
print(num)
Check
-1
Exercise 7
Check
Computer logic
Have you noticed that the conditions we've used so far have been very simple, not to say, quite primitive?
The conditions we use in real life are much more complex. Let's look at this sentence:
If we have some free time, and the weather is good, we will go for a walk.
Juniper
Business
Use Only
We've used the conjunction and , which means that going for a walk depends on the simultaneous
fulfilment of these two conditions. In the language of logic, such a connection of conditions is called
a conjunction. And now another example:
If you are in the mall or I am in the mall, one of us will buy a gift for Mom.
The appearance of the word or means that the purchase depends on at least one of these conditions. In
logic, such a compound is called a disjunction.
It's clear that Python must have operators to build conjunctions and disjunctions. Without them, the
expressive power of the language would be substantially weakened. They're called logical operators.
and
One logical conjunction operator in Python is the word and. It's a binary operator with a priority that is
lower than the one expressed by the comparison operators. It allows us to code complex conditions
without the use of parentheses like this one:
The result provided by the and operator can be determined on the basis of the truth table.
If we consider the conjunction of A and B , the set of possible values of arguments and corresponding
values of the conjunction looks as follows:
or
A disjunction operator is the word or . It's a binary operator with a lower priority than and (just
like + compared to * ). Its truth table is as follows:
Argument A Argument B A or B
False False False
False True True
Juniper
Business
Use Only
True False True
True True True
not
In addition, there's another operator that can be applied for constructing conditions. It's a unary operator
performing a logical negation. Its operation is simple: it turns truth into falsehood and falsehood into
truth.
This operator is written as the word not , and its priority is very high: the same as the unary + and - .
Its truth table is simple:
Logical expressions
Let's create a variable named var and assign 1 to it. The following conditions are pairwise equivalent:
# Example 1:
print(var > 0)
print(not (var <= 0))
# Example 2:
print(var != 0)
print(not (var == 0))
Juniper
Business
Use Only
Note how the parentheses have been used to code the expressions - we put them there to improve
readability.
We should add that none of these two-argument operators can be used in the abbreviated form known
as op= . This exception is worth remembering.
The result of their operations is one of these values: False or True . This means that this snippet will
assign the value True to the j variable if i is not zero; otherwise, it will be False .
i = 1
j = not not i
Bitwise operators
However, there are four operators that allow you to manipulate single bits of data. They are
called bitwise operators.
They cover all the operations we mentioned before in the logical context, and one additional operator. This
is the xor (as in exclusive or) operator, and is denoted as ^ (caret).
Juniper
Business
Use Only
Let's make it easier:
Let us add an important remark: the arguments of these operators must be integers; we must not use floats
here.
The difference in the operation of the logical and bit operators is important: the logical operators do not
penetrate into the bit level of its argument. They're only interested in the final integer value.
Bitwise operators are stricter: they deal with every bit separately. If we assume that the integer variable
occupies 64 bits (which is common in modern computer systems), you can imagine the bitwise operation
as a 64-fold evaluation of the logical operator for each pair of bits of the arguments. This analogy is
obviously imperfect, as in the real world all these 64 operations are performed at the same time
(simultaneously).
i = 15
j = 22
If we assume that the integers are stored with 32 bits, the bitwise image of the two variables will be as
follows:
i: 00000000000000000000000000001111
j: 00000000000000000000000000010110
log = i and j
Juniper
Business
Use Only
We are dealing with a logical conjunction here. Let's trace the course of the calculations. Both
variables i and j are not zeros, so will be deemed to represent True . Consulting the truth table for
the and operator, we can see that the result will be True . No other operations are performed.
log: True
bit = i & j
The & operator will operate with each pair of corresponding bits separately, producing the values of the
relevant bits of the result. Therefore, the result will be as follows:
i 00000000000000000000000000001111
j 00000000000000000000000000010110
bit = i & j 00000000000000000000000000000110
Let's look at the negation operators now. First the logical one:
logneg = not i
The logneg variable will be set to False - nothing more needs to be done.
bitneg = ~i
It may be a bit surprising: the bitneg variable value is -16 . This may seem strange, but isn't at all. If
you wish to learn more, you should check out the binary numeral system and the rules governing two's
complement numbers.
i 00000000000000000000000000001111
bitneg = ~i 11111111111111111111111111110000
Juniper
Business
Use Only
Each of these two-argument operators can be used in abbreviated form. These are the examples of their
equivalent notations:
x = x & y x &= y
x = x | y x |= y
x = x ^ y x ^= y
flag_register = 0x1234
The variable stores the information about various aspects of system operation. Each bit of the variable
stores one yes/no value. You've also been told that only one of these bits is yours - the third (remember
that bits are numbered from zero, and bit number zero is the lowest one, while the highest is number 31).
The remaining bits are not allowed to change, because they're intended to store other data. Here's your bit
marked with the letter x :
flag_register = 0000000000000000000000000000x000
1. Check the state of your bit - you want to find out the value of your bit; comparing the whole variable
to zero will not do anything, because the remaining bits can have completely unpredictable values, but you
can use the following conjunction property:
x & 1 = x
x & 0 = 0
If you apply the & operation to the flag_register variable along with the following bit image:
00000000000000000000000000001000
(note the 1 at your bit's position) as the result, you obtain one of the following bit strings:
Juniper
Business
Use Only
Such a sequence of zeros and ones, whose task is to grab the value or to change the selected bits, is called
a bit mask.
Let's build a bit mask to detect the state of your bit. It should point to the third bit. That bit has the weight
of 23 = 8 . A suitable mask could be created by the following declaration:
the_mask = 8
You can also make a sequence of instructions depending on the state of your bit i here it is:
2. Reset your bit - you assign a zero to the bit while all the other bits must remain unchanged; let's use the
same property of the conjunction as before, but let's use a slightly different mask - exactly as below:
11111111111111111111111111110111
Note that the mask was created as a result of the negation of all the bits of the_mask variable. Resetting
the bit is simple, and looks like this (choose the one you like more):
3. Set your bit - you assign a 1 to your bit, while all the remaining bits must remain unchanged; use the
following disjunction property:
x | 1 = 1
x | 0 = x
You're now ready to set your bit with one of the following instructions:
Juniper
Business
Use Only
flag_register |= the_mask
4. Negate your bit - you replace a 1 with a 0 and a 0 with a 1 . You can use an interesting property of
the xor operator:
x ^ 1 = ~x
x ^ 0 = x
You already apply this operation very often and quite unconsciously. How do you multiply
any number by ten? Take a look:
12345 × 10 = 123450
As you can see, multiplying by ten is in fact a shift of all the digits to the left and filling the
resulting gap with zero.
12340 ÷ 10 = 1234
The same kind of operation is performed by the computer, but with one difference: as two is
the base for binary numbers (not 10), shifting a value one bit to the left thus
Juniper
Business
Use Only
corresponds to multiplying it by two; respectively, shifting one bit to the right is like
dividing by two (notice that the rightmost bit is lost).
The shift operators in Python are a pair of digraphs: << and >> , clearly suggesting in which
direction the shift will act.
The left argument of these operators is an integer value whose bits are shifted. The
right argument determines the size of the shift.
The priority of these operators is very high. You'll see them in the updated table of priorities,
which we'll show you at the end of this section.
17 68 8
output
Note:
And here is the updated priority table, containing all the operators introduced so far:
Priority Operator
1 ~ , + , - unary
2 **
3 * , / , // , %
4 + , - binary
5 << , >>
6 < , <= , > , >=
Juniper
Business
Use Only
7 == , !=
8 &
9 |
10 = , += , -= , *= , /= , %= , &= , ^= , |= , >>= , <<=
Key takeaways
and → if both operands are true, the condition is true, e.g., (True and True) is True ,
or → if any of the operands are true, the condition is true, e.g., (True or False) is True ,
not → returns false if the result is true, and returns true if the result is false, e.g., not
True is False .
2. You can use bitwise operators to manipulate single bits of data. The following sample data:
will be used to illustrate the meaning of bitwise operators in Python. Analyze the examples below:
& does a bitwise and, e.g., x & y = 0 , which is 0000 0000 in binary,
| does a bitwise or, e.g., x | y = 31 , which is 0001 1111 in binary,
˜ does a bitwise not, e.g., ˜ x = 240 *, which is 1111 0000 in binary,
^ does a bitwise xor, e.g., x ^ y = 31 , which is 0001 1111 in binary,
>> does a bitwise right shift, e.g., y >> 1 = 8 , which is 0000 1000 in binary,
<< does a bitwise left shift, e.g., y << 3 = , which is 1000 0000 in binary,
* -16 (decimal from signed 2's complement) -- read more about the Two's complement operation.
Exercise 1
x = 1
y = 0
Juniper
Business
Use Only
print(not(z))
Check
False
Exercise 2
x = 4
y = 1
a = x & y
b = x | y
c = ~x # tricky!
d = x ^ 5
e = x >> 2
f = x << 2
print(a, b, c, d, e, f)
Check
0 5 -5 1 1 16
var1 = int(input())
var2 = int(input())
var3 = int(input())
var4 = int(input())
var5 = int(input())
var6 = int(input())
:
:
Juniper
Business
Use Only
If you don't think that this is a complicated task, then take a piece of paper and write a program that:
You should find that you don't even have enough paper to complete the task.
So far, you've learned how to declare variables that are able to store exactly one given value at a time.
Such variables are sometimes called scalars by analogy with mathematics. All the variables you've used so
far are actually scalars.
Think of how convenient it would be to declare a variable that could store more than one value. For
example, a hundred, or a thousand or even ten thousand. It would still be one and the same variable, but
very wide and capacious. Sounds appealing? Perhaps, but how would it handle such a container full of
different values? How would it choose just the one you need?
What if you could just number them? And then say: give me the value number 2; assign the value number
15; increase the value number 10000.
We'll show you how to declare such multi-value variables. We'll do this with the example we just
suggested. We'll write a program that sorts a sequence of numbers. We won't be particularly ambitious -
we'll assume that there are exactly five numbers.
Let's create a variable called numbers ; it's assigned with not just one number, but is filled with a list
consisting of five values (note: the list starts with an open square bracket and ends with a closed
square bracket; the space between the brackets is filled with five numbers separated by commas).
numbers = [10, 5, 7, 2, 1]
Let's say the same thing using adequate terminology: numbers is a list consisting of five values, all of
them numbers. We can also say that this statement creates a list of length equal to five (as in there are five
elements inside it).
The elements inside a list may have different types. Some of them may be integers, others floats, and yet
others may be lists.
Python has adopted a convention stating that the elements in a list are always numbered starting from
zero. This means that the item stored at the beginning of the list will have the number zero. Since there are
five elements in our list, the last of them is assigned the number four. Don't forget this.
You'll soon get used to it, and it'll become second nature.
Before we go any further in our discussion, we have to state the following: our list is a collection of
elements, but each element is a scalar.
Juniper
Business
Use Only
Indexing lists
How do you change the value of a chosen element in the list?
Let's assign a new value of 111 to the first element in the list. We do it this way:
numbers = [10, 5, 7, 2, 1]
print("Original list content:", numbers) # Printing original list
content.
numbers[0] = 111
print("New list content: ", numbers) # Current list content.
And now we want the value of the fifth element to be copied to the second element -
can you guess how to do it?
numbers = [10, 5, 7, 2, 1]
print("Original list content:", numbers) # Printing original list
content.
numbers[0] = 111
print("\nPrevious list content:", numbers) # Printing previous list
content.
The value inside the brackets which selects one element of the list is called an index, while
the operation of selecting an element from the list is known as indexing.
We're going to use the print() function to print the list content each time we make the
changes. This will help us follow each step more carefully and see what's going on after a
particular list modification.
Note: all the indices used so far are literals. Their values are fixed at runtime, but any
expression can be the index, too. This opens up lots of possibilities.
Juniper
Business
Use Only
Each of the list's elements may be accessed separately. For example, it can be printed:
Assuming that all of the previous operations have been completed successfully, the snippet
will send 111 to the console.
As you can see in the editor, the list may also be printed as a whole - just like here:
As you've probably noticed before, Python decorates the output in a way that suggests that
all the presented values form a list. The output from the example snippet above looks like
this:
[111, 1, 7, 2, 1]
output
The len() function
The length of a list may vary during execution. New elements may be added to the list,
while others may be removed from it. This means that the list is a very dynamic entity.
If you want to check the list's current length, you can use a function named len() (its name
comes from length).
The function takes the list's name as an argument, and returns the number of elements
currently stored inside the list (in other words - the list's length).
Look at the last line of code in the editor, run the program and check what value it will print
to the console. Can you guess?
numbers = [10, 5, 7, 2, 1]
print("Original list content:", numbers) # Printing original list content.
numbers[0] = 111
print("\nPrevious list content:", numbers) # Printing previous list content.
Juniper
Business
Use Only
print("Previous list content:", numbers) # Printing previous list content.
List length: 5
You have to point to the element to be removed - it'll vanish from the list, and the list's
length will be reduced by one.
Look at the snippet below. Can you guess what output it will produce? Run the program in
the editor and check.
del numbers[1]
print(len(numbers))
print(numbers)
You can't access an element which doesn't exist - you can neither get its value nor assign
it a value. Both of these instructions will cause runtime errors now:
print(numbers[4])
numbers[4] = 1
Add the snippet above after the last line of code in the editor, run the program and check
what happens.
Note: we've removed one of the list's elements - there are only four elements in the list now.
This means that element number four doesn't exist.
numbers = [10, 5, 7, 2, 1]
print("Original list content:", numbers) # Printing original list content.
Juniper
Business
Use Only
numbers[0] = 111
print("\nPrevious list content:", numbers) # Printing previous list content.
###
List's length: 5
New list's length: 4
numbers.pop()
An element with an index equal to -1 is the last one in the list.
print(numbers[-1])
The example snippet will output 1 . Run the program and check.
Similarly, the element with an index equal to -2 is the one before last in the list.
print(numbers[-2])
Juniper
Business
Use Only
The example snippet will output 2 .
The last accessible element in our list is numbers[-4] (the first one) - don't try to go any
further!
numbers = [111, 7, 2, 1]
print(numbers[-1])
print(numbers[-2])
1
2
Level of difficulty
Very easy
Objectives
Familiarize the student with:
Scenario
There once was a hat. The hat contained no rabbit, but a list of five numbers: 1 , 2 , 3 , 4 ,
and 5 .
write a line of code that prompts the user to replace the middle number in the list
with an integer number entered by the user (Step 1)
write a line of code that removes the last element from the list (Step 2)
write a line of code that prints the length of the existing list (Step 3).
A function doesn't belong to any data - it gets data, it may create new data and it (generally) produces a
result.
Juniper
Business
Use Only
A method does all these things, but is also able to change the state of a selected entity.
A method is owned by the data it works for, while a function is owned by the whole code.
This also means that invoking a method requires some specification of the data from which the method is
invoked.
It may sound puzzling here, but we'll deal with it in depth when we delve into object-oriented
programming.
result = function(arg)
result = data.method(arg)
Note: the name of the method is preceded by the name of the data which owns the method. Next, you add
a dot, followed by the method name, and a pair of parenthesis enclosing the arguments.
The method will behave like a function, but can do something more - it can change the internal state of
the data from which it has been invoked.
You may ask: why are we talking about methods, not about lists?
This is an essential issue right now, as we're going to show you how to add new elements to an existing
list. This can be done with methods owned by all the lists, not by functions.
Juniper
Business
Use Only
list.append(value)
Such an operation is performed by a method named append() . It takes its argument's value
and puts it at the end of the list which owns the method.
The insert() method is a bit smarter - it can add a new element at any place in the list,
not only at the end.
list.insert(location, value)
the first shows the required location of the element to be inserted; note: all the
existing elements that occupy locations to the right of the new element (including
the one at the indicated position) are shifted to the right, in order to make space for
the new element;
the second is the element to be inserted.
Look at the code in the editor. See how we use the append() and insert() methods. Pay
attention to what happens after using insert(): the former first element is now the
second, the second the third, and so on.
Add the following snippet after the last line of code in the editor:
Print the final list content to the screen and see what happens. The snippet above snippet
inserts 333 into the list, making it the second element. The former second element becomes
the third, the third the fourth, and so on.
numbers = [111, 7, 2, 1]
print(len(numbers))
print(numbers)
###
Juniper
Business
Use Only
numbers.append(4)
print(len(numbers))
print(numbers)
###
numbers.insert(0, 222)
print(len(numbers))
print(numbers)
4
[111, 7, 2, 1]
5
[111, 7, 2, 1, 4]
6
[222, 111, 7, 2, 1, 4]
Take a look at the snippet in the editor. Try to guess its output after the for loop execution.
Run the program to check if you were right.
It'll be a sequence of consecutive integer numbers from 1 (you then add one to all the
appended values) to 5 .
for i in range(5):
my_list.insert(0, i + 1)
print(my_list)
what will happen now? Run the program and check if this time you were right, too.
Juniper
Business
Use Only
You should get the same sequence, but in reverse order (this is the merit of using
the insert() method).
for i in range(5):
my_list.append(i + 1)
print(my_list)
[1, 2, 3, 4, 5]
Let's assume that you want to calculate the sum of all the values stored in
the my_list list.
You need a variable whose sum will be stored and initially assigned a value of 0 - its name
will be total . (Note: we're not going to name it sum as Python uses the same name for one
of its built-in functions - sum() . Using the same name would generally be considered a
bad practice.) Then you add to it all the elements of the list using the for loop. Take a look
at the snippet in the editor.
Juniper
Business
Use Only
This modified snippet shows how it works:
my_list = [10, 1, 8, 3, 5]
total = 0
for i in my_list:
total += i
print (total)
the for instruction specifies the variable used to browse the list ( i here) followed by
the in keyword and the name of the list being processed ( my_list here)
the i variable is assigned the values of all the subsequent list's elements, and the
process occurs as many times as there are elements in the list;
this means that you use the i variable as a copy of the elements' values, and you
don't need to use indices;
the len() function is not needed here, either.
my_list = [10, 1, 8, 3, 5]
total = 0
for i in range(len(my_list)):
total += my_list[i]
print(total)
27
Lists in action
Let's leave lists aside for a short moment and look at one intriguing issue.
Imagine that you need to rearrange the elements of a list, i.e., reverse the order of the
elements: the first and the fifth as well as the second and fourth elements will be swapped.
The third one will remain untouched.
Juniper
Business
Use Only
variable_1 = 1
variable_2 = 2
variable_2 = variable_1
variable_1 = variable_2
If you do something like this, you would lose the value previously stored in variable_2 .
Changing the order of the assignments will not help. You need a third variable that serves
as an auxiliary storage.
variable_1 = 1
variable_2 = 2
auxiliary = variable_1
variable_1 = variable_2
variable_2 = auxiliary
Python offers a more convenient way of doing the swap - take a look:
variable_1 = 1
variable_2 = 2
Lists in action
Now you can easily swap the list's elements to reverse their order:
my_list = [10, 1, 8, 3, 5]
print (my_list)
Juniper
Business
Use Only
Run the snippet. Its output should look like this:
[5, 3, 8, 1, 10]
output
Will it still be acceptable with a list containing 100 elements? No, it won't.
Can you use the for loop to do the same thing automatically, irrespective of the list's
length? Yes, you can.
my_list = [10, 1, 8, 3, 5]
length = len(my_list)
print(my_list)
Note:
we've assigned the length variable with the current list's length (this makes our
code a bit clearer and shorter)
we've launched the for loop to run through its body length // 2 times (this works
well for lists with both even and odd lengths, because when the list contains an odd
number of elements, the middle one remains untouched)
we've swapped the ith element (from the beginning of the list) with the one with an
index equal to (length - i - 1) (from the end of the list); in our example,
for i equal to 0 the (lenght - i - 1) gives 4 ; for i equal to 1 , it gives 3 - this is
exactly what we needed.
Lists are extremely useful, and you'll encounter them very often.
Juniper
Business
Use Only
Estimated time
10-15 minutes
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
The Beatles were one of the most popular music group of the 1960s, and the best-selling
band in history. Some people consider them to be the most influential act of the rock era.
Indeed, they were included in Time magazine's compilation of the 20th Century's 100 most
influential people.
The band underwent many line-up changes, culminating in 1962 with the line-up of John
Lennon, Paul McCartney, George Harrison, and Richard Starkey (better known as Ringo
Starr).
Write a program that reflects these changes and lets you practice with the concept of lists.
Your task is to:
By the way, are you a Beatles fan? (The Beatles is one of Greg's favorite bands. But
wait...who's Greg...?)
beatles = []
Juniper
Business
Use Only
print("Step 1:", beatles)
beatles.append("John")
beatles.append("Paul")
beatles.append("George")
print("Step 2:", beatles)
for i in range(2):
if i == 0:
beatles.append("Stu")
else:
beatles.append("pete")
print("Step 3:", beatles)
del beatles[len(beatles)-2:len(beatles)-1]
print("Step 4:", beatles)
beatles.insert(0,"ringo")
print("Step 5:", beatles)
Step 1: []
Step 2: ['John', 'Paul', 'George']
Step 3: ['John', 'Paul', 'George', 'Stu', 'pete']
Step 4: ['John', 'Paul', 'George', 'pete']
Step 5: ['ringo', 'John', 'Paul', 'George', 'pete']
The Fab 5
list.insert(i, elem)
Here, elem is inserted to the list at the i index. All the elements after elem are
th
Juniper
Business
Use Only
insert() Parameters
The insert() method doesn't return anything; returns None . It only updates the
current list.
# vowel list
vowel = ['a', 'e', 'i', 'u']
Juniper
Business
Use Only
Output
# number tuple
number_tuple = (3, 4)
Output
list1.extend(iterable)
Here, all the elements of iterable are added to the end of list1 .
Juniper
Business
Use Only
extend() Parameters
As mentioned, the extend() method takes an iterable such as list, tuple, string
etc.
The extend() method modifies the original list. It doesn't return any value.
# languages list
languages = ['French', 'English']
Output
Juniper
Business
Use Only
Example 2: Add Elements of Tuple and Set to List
# languages list
languages = ['French']
# languages tuple
languages_tuple = ('Spanish', 'Portuguese')
# languages set
languages_set = {'Chinese', 'Japanese'}
Output
You can also append all elements of an iterable to the list using:
1. the + operator
a = [1, 2]
b = [3, 4]
a += b # a = a + b
Juniper
Business
Use Only
# Output: [1, 2, 3, 4]
print('a =', a)
Output
a = [1, 2, 3, 4]
a = [1, 2]
b = [3, 4]
a[len(a):] = b
# Output: [1, 2, 3, 4]
print('a =', a)
Output
a = [1, 2, 3, 4]
If you need to add an element to the end of a list, you can use
the append() method.
a1 = [1, 2]
a2 = [1, 2]
b = (3, 4)
# a1 = [1, 2, 3, 4]
a1.extend(b)
print(a1)
Juniper
Business
Use Only
print(a2)
Output
[1, 2, 3, 4]
list.append(item)
append() Parameters
Juniper
Business
Use Only
Example 1: Adding Element to a List
# animals list
animals = ['cat', 'dog', 'rabbit']
Output
# animals list
animals = ['cat', 'dog', 'rabbit']
Output
Juniper
Business
Use Only
It is important to notice that, a single item ( wild_animals list) is added to
the animals list in the above program.
If you need to add items of a list to another list (rather than the list itself),
use the extend() method.
l.clear()
print(l)
# []
source: list_remove_item.py
Remove an item by index and get its value: pop()
You can remove the item at the specified position and get its value with pop() .
The index at the beginning is 0 (zero-based indexing).
l = list(range(10))
print(l)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l.pop(0))
Juniper
Business
Use Only
# 0
print(l)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l.pop(3))
# 4
print(l)
# [1, 2, 3, 5, 6, 7, 8, 9]
source: list_remove_item.py
You can use negative values to specify the position from the end. The index at the end is -1 .
print(l.pop(-2))
# 8
print(l)
# [1, 2, 3, 5, 6, 7, 9]
source: list_remove_item.py
print(l.pop())
# 9
print(l)
# [1, 2, 3, 5, 6, 7]
source: list_remove_item.py
# print(l.pop(100))
# IndexError: pop index out of range
source: list_remove_item.py
Remove an item by value: remove()
You can remove the first item from the list where its value is equal to the specified value
with remove() .
l = ['Alice', 'Bob', 'Charlie', 'Bob', 'Dave']
print(l)
# ['Alice', 'Bob', 'Charlie', 'Bob', 'Dave']
l.remove('Alice')
print(l)
# ['Bob', 'Charlie', 'Bob', 'Dave']
source: list_remove_item.py
If the list contains more than one matching the specified value, only the first one is deleted.
l.remove('Bob')
print(l)
# ['Charlie', 'Bob', 'Dave']
source: list_remove_item.py
Juniper
Business
Use Only
Specifying a nonexistent value raises an error.
# l.remove('xxx')
# ValueError: list.remove(x): x not in list
source: list_remove_item.py
Sponsored Link
Remove items by index or slice: del
clear() , pop() , and remove() are methods of list . You can also remove elements from a
list with del statements.
Specify the item to be deleted by index. The first index is 0 , and the last index is -1 .
l = list(range(10))
print(l)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
del l[0]
print(l)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
del l[-1]
print(l)
# [1, 2, 3, 4, 5, 6, 7, 8]
del l[6]
print(l)
# [1, 2, 3, 4, 5, 6, 8]
source: list_remove_item.py
l = list(range(10))
print(l)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
del l[2:5]
print(l)
# [0, 1, 5, 6, 7, 8, 9]
l = list(range(10))
del l[:3]
print(l)
# [3, 4, 5, 6, 7, 8, 9]
l = list(range(10))
del l[4:]
print(l)
# [0, 1, 2, 3]
l = list(range(10))
del l[-3:]
print(l)
# [0, 1, 2, 3, 4, 5, 6]
source: list_remove_item.py
Juniper
Business
Use Only
It is also possible to delete all items by specifying the entire range.
l = list(range(10))
del l[:]
print(l)
# []
source: list_remove_item.py
You can also specify step as [start:stop:step] .
l = list(range(10))
del l[2:8:2]
print(l)
# [0, 1, 3, 5, 7, 8, 9]
l = list(range(10))
del l[::3]
print(l)
# [1, 2, 4, 5, 7, 8]
source: list_remove_item.py
Removing items that satisfy the condition is equivalent extracting items that do not satisfy the
condition.
print(l)
Juniper
Business
Use Only
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
source: list_remove_item.py
See the following article for details on extracting elements using list comprehensions.
Key takeaways
1. The list is a type of data in Python used to store multiple objects. It is an ordered and mutable
collection of comma-separated items between square brackets, e.g.:
Juniper
Business
Use Only
print (my_list) # outputs: ['first', 1, '?', True, 'I am a string',
256, 0, 'last']
You will learn more about nesting in module 3.1.7 - for the time being, we just want you to be aware that
something like this is possible, too.
my_list = [1, 2, 3, 4]
del my_list[2]
print (my_list) # outputs: [1, 2, 4]
Again, you will learn more about this in module 3.1.6 - don't worry. For the time being just try to
experiment with the above code and check how changing it affects the output.
6. The len() function may be used to check the list's length, e.g.:
del my_list[2]
print (len(my_list)) # outputs 4
Juniper
Business
Use Only
Exercise 1
lst = [1, 2, 3, 4, 5]
lst.insert(1, 6)
del lst[0]
lst.append(1)
print(lst)
Check
[6, 2, 3, 4, 5, 1]
Exercise 2
lst = [1, 2, 3, 4, 5]
lst_2 = []
add = 0
print(lst_2)
Check
Exercise 3
lst = []
del lst
print(lst)
Check
Juniper
Business
Use Only
Exercise 4
Check
[2, 3]
increasing (or more precisely - non-decreasing) - if in every pair of adjacent elements, the former
element is not greater than the latter;
decreasing (or more precisely - non-increasing) - if in every pair of adjacent elements, the former
element is not less than the latter.
In the following sections, we'll sort the list in increasing order, so that the numbers will be ordered from
the smallest to the largest.
8 10 6 2 4
We'll try to use the following approach: we'll take the first and the second elements and compare them; if
we determine that they're in the wrong order (i.e., the first is greater than the second), we'll swap them
round; if their order is valid, we'll do nothing. A glance at our list confirms the latter - the elements 01 and
02 are in the proper order, as in 8 < 10 .
Now look at the second and the third elements. They're in the wrong positions. We have to swap them:
8 6 10 2 4
We go further, and look at the third and the fourth elements. Again, this is not what it's supposed to be like.
We have to swap them:
8 6 2 10 4
Juniper
Business
Use Only
Now we check the fourth and the fifth elements. Yes, they too are in the wrong positions. Another swap
occurs:
8 6 2 4 10
The first pass through the list is already finished. We're still far from finishing our job, but something
curious has happened in the meantime. The largest element, 10 , has already gone to the end of the list.
Note that this is the desired place for it. All the remaining elements form a picturesque mess, but this one
is already in place.
Now, for a moment, try to imagine the list in a slightly different way - namely, like this:
10
4
2
6
8
Look - 10 is at the top. We could say that it floated up from the bottom to the surface, just like the bubble
in a glass of champagne. The sorting method derives its name from the same observation - it's called
a bubble sort.
Now we start with the second pass through the list. We look at the first and second elements - a swap is
necessary:
6 8 2 4 10
Time for the second and third elements: we have to swap them too:
6 2 8 4 10
Now the third and fourth elements, and the second pass is finished, as 8 is already in place:
6 2 4 8 10
Juniper
Business
Use Only
We start the next pass immediately. Watch the first and the second elements carefully - another swap is
needed:
2 6 4 8 10
Now 6 needs to go into place. We swap the second and the third elements:
2 4 6 8 10
The list is already sorted. We have nothing more to do. This is exactly what we want.
As you can see, the essence of this algorithm is simple: we compare the adjacent elements, and by
swapping some of them, we achieve our goal.
Let's code in Python all the actions performed during a single pass through the list, and then we'll consider
how many passes we actually need to perform it. We haven't explained this so far, and we'll do that a little
later.
Sorting a list
How many passes do we need to sort the entire list?
We solve this issue in the following way: we introduce another variable; its task is to
observe if any swap has been done during the pass or not; if there is no swap, then the list is
already sorted, and nothing more has to be done. We create a variable named swapped ,
and we assign a value of False to it, to indicate that there are no swaps. Otherwise, it will
be assigned True .
You should be able to read and understand this program without any problems:
Juniper
Business
Use Only
while swapped:
swapped = False # no swaps so far
for i in range(len(my_list) - 1):
if my_list[i] > my_list[i + 1]:
swapped = True # a swap occurred!
my_list[i], my_list[i + 1] = my_list[i + 1], my_list[i]
print (my_list)
Python, however, has its own sorting mechanisms. No one needs to write their own sorts, as
there is a sufficient number of ready-to-use tools.
We explained this sorting system to you because it's important to learn how to process a
list's contents, and to show you how real sorting may work.
If you want Python to sort your list, you can do it like this:
It is as simple as that.
[2, 4, 6, 8, 10]
output
As you can see, all the lists have a method named sort() , which sorts them as fast as
possible. You've already learned about some of the list methods before, and you're going to
learn more about others very soon.
Juniper
Business
Use Only
Key takeaways
1. You can use the sort() method to sort elements of a list, e.g.:
lst = [5, 3, 1, 2, 4]
print (lst)
lst .sort()
print (lst) # outputs: [1, 2, 3, 4, 5]
2. There is also a list method called reverse() , which you can use to reverse the list, e.g.:
lst = [5, 3, 1, 2, 4]
print (lst)
lst .reverse()
print (lst) # outputs: [4, 2, 1, 3, 5]
Exercise 1
print(lst)
Check
Exercise 2
Juniper
Business
Use Only
What is the output of the following snippet?
a = 3
b = 1
c = 2
lst = [a, c, b]
lst.sort()
print(lst)
Check
[1, 2, 3]
Exercise 3
a = "A"
b = "B"
c = "C"
d = " "
lst = [a, b, c, d]
lst.reverse()
print(lst)
Check
We want you to memorize it - it may affect your future programs, and cause severe
problems if forgotten or overlooked.
Juniper
Business
Use Only
The program:
The surprising part is the fact that the program will output: [2] , not [1] , which seems to be
the obvious solution.
Lists (and many other complex Python entities) are stored in different ways than ordinary
(scalar) variables.
Read these two lines once more - the difference is essential for understanding what we are
going to talk about next.
The assignment: list_2 = list_1 copies the name of the array, not its contents. In effect,
the two names ( list_1 and list_2 ) identify the same location in the computer memory.
Modifying one of them affects the other, and vice versa.
Powerful slices
Fortunately, the solution is at your fingertips - its name is the slice.
A slice is an element of Python syntax that allows you to make a brand new copy of a list,
or parts of a list.
This is exactly what you need. Take a look at the snippet below:
list_1 = [1]
list_2 = list_1[:]
list_1[0] = 2
print(list_2)
Juniper
Business
Use Only
Its output is [1] .
This inconspicuous part of the code described as [:] is able to produce a brand new list.
my_list[start:end]
As you can see, it resembles indexing, but the colon inside makes a big difference.
A slice of this form makes a new (target) list, taking elements from the source list - the
elements of the indices from start to end - 1 .
Note: not to end but to end - 1 . An element with an index equal to end is the first element
which does not take part in the slicing.
Using negative values for both start and end is possible (just like in indexing).
my_list = [10, 8, 6, 4, 2]
new_list = my_list[1:3]
print(new_list)
The new_list list will have end - start (3 - 1 = 2) elements - the ones with indices equal
to 1 and 2 (but not 3 ).
my_list[start:end]
To repeat:
Juniper
Business
Use Only
This is how negative indices work with the slice:
my_list = [10, 8, 6, 4, 2]
new_list = my_list[1:-1]
print(new_list)
[8, 6, 4]
output
If the start specifies an element lying further than the one described by the end (from the
list's beginning point of view), the slice will be empty:
my_list = [10, 8, 6, 4, 2]
new_list = my_list[-1:1]
print(new_list)
[]
output
Slices: continued
If you omit the start in your slice, it is assumed that you want to get a slice beginning at the
element with index 0 .
my_list[:end]
Juniper
Business
Use Only
is a more compact equivalent of:
my_list[0:end]
my_list = [10, 8, 6, 4, 2]
new_list = my_list[:3]
print(new_list)
Similarly, if you omit the end in your slice, it is assumed that you want the slice to end at the
element with the index len(my_list) .
my_list[start:]
my_list[start:len(my_list)]
my_list = [10, 8, 6, 4, 2]
new_list = my_list[3:]
print(new_list)
Slices: continued
As we've said before, omitting both start and end makes a copy of the whole list:
Juniper
Business
Use Only
my_list = [10, 8, 6, 4, 2]
new_list = my_list[:]
print(new_list)
The previously described del instruction is able to delete more than just a list's element
at once - it can delete slices too:
my_list = [10, 8, 6, 4, 2]
del my_list[1:3]
print(my_list)
my_list = [10, 8, 6, 4, 2]
del my_list[:]
print(my_list)
Removing the slice from the code changes its meaning dramatically.
Take a look:
my_list = [10, 8, 6, 4, 2]
del my_list
print(my_list)
Juniper
Business
Use Only
The del instruction will delete the list itself, not its content.
The print() function invocation from the last line of the code will then cause a runtime
error.
The in and not in operators
Python offers two very powerful operators, able to look through the list in order to check
whether a specific value is stored inside the list or not.
elem in my_list
elem not in my_list
The first of them ( in ) checks if a given element (its left argument) is currently stored
somewhere inside the list (the right argument) - the operator returns True in this case.
The second ( not in ) checks if a given element (its left argument) is absent in a list - the
operator returns True in this case.
Look at the code in the editor. The snippet shows both operators in action. Can you guess
its output? Run the program to check if you were right.
print(5 in my_list)
print(5 not in my_list)
print(12 in my_list)
False
True
True
Juniper
Business
Use Only
The first of them tries to find the greater value in the list. Look at the code in the editor.
The concept is rather simple - we temporarily assume that the first element is the largest
one, and check the hypothesis against all the remaining elements in the list.
The code may be rewritten to make use of the newly introduced form of the for loop:
for i in my_list:
if i > largest:
largest = i
print (largest)
The program above performs one unnecessary comparison, when the first element is
compared with itself, but this isn't a problem at all.
for i in my_list[1:]:
if i > largest:
largest = i
print (largest)
The question is: which of these two actions consumes more computer resources - just one
comparison, or slicing almost all of a list's elements?
Juniper
Business
Use Only
Now let's find the location of a given element inside a list:
for i in range(len(my_list)):
found = my_list[i] == to_find
if found:
break
if found:
print("Element found at index", i)
else :
print("absent")
Note:
Let's assume that you've chosen the following numbers in the lottery: 3 , 7 , 11 , 42 , 34 , 49 .
print (hits)
Note:
Juniper
Business
Use Only
the bets list stores your bets;
the hits variable counts your hits.
Estimated time
10-15 minutes
Level of difficulty
Easy
Objectives
Familiarize the student with:
list indexing;
utilizing the in and not in operators.
Scenario
Imagine a list - not very long, not very complicated, just a simple list containing some integer
numbers. Some of these numbers may be repeated, and this is the clue. We don't want any
repetitions. We want them to be removed.
Your task is to write a program which removes all the number repetitions from the list. The
goal is to have a list in which all the numbers appear not more than once.
Note: assume that the source list is hard-coded inside the code - you don't have to enter it
from the keyboard. Of course, you can improve the code and add a part that can carry out a
conversation with the user and obtain all the data from her/him.
Hint: we encourage you to create a new list as a temporary work area - you don't need to
update the list in situ.
We've provided no test data, as that would be too easy. You can use our skeleton instead.
my_list = [1, 2, 4, 4, 1, 4, 2, 6, 2, 9]
new_list = []
for i in my_list:
if i in new_list:
continue
else:
new_list.append(i)
my_list = new_list
print("The list with unique elements only:")
print(my_list)
Juniper
Business
Use Only
The list with unique elements only:
[1, 2, 4, 6, 9]
Key takeaways
1. If you have a list l1 , then the following assignment: l2 = l1 does not make a copy of the l1 list, but
makes the variables l1 and l2 point to one and the same list in memory. For example:
vehicles_two = vehicles_one
del vehicles_one[0] # deletes 'car'
print (vehicles_two) # outputs: ['bicycle', 'motor']
2. If you want to copy a list or part of the list, you can do it by performing slicing:
4. The start and end parameters are optional when performing a slice: list[start:end] , e.g.:
my_list = [1, 2, 3, 4, 5]
slice_one = my_list[2: ]
slice_two = my_list[ :2]
slice_three = my_list[-2: ]
Juniper
Business
Use Only
print (slice_two) # outputs: [1, 2]
print (slice_three) # outputs: [4, 5]
my_list = [1, 2, 3, 4, 5]
del my_list[0:2]
print (my_list) # outputs: [3, 4, 5]
del my_list[:]
print (my_list) # deletes the list content, outputs: []
6. You can test if some items exist in a list or not using the keywords in and not in , e.g.:
Exercise 1
del list_1[0]
del list_2[0]
print(list_3)
Check
['C']
Juniper
Business
Use Only
Exercise 2
del list_1[0]
del list_2
print(list_3)
Check
['B', 'C']
Exercise 3
del list_1[0]
del list_2[:]
print(list_3)
Check
[]
Exercise 4
Juniper
Business
Use Only
del list_1[0]
del list_2[0]
print(list_3)
Check
Exercise 5
Insert in or not in instead of ??? so that the code outputs the expected result.
Lists in lists
Lists can consist of scalars (namely numbers) and elements of a much more complex
structure (you've already seen such examples as strings, booleans, or even other lists in the
previous Section Summary lessons). Let's have a closer look at the case where a list's
elements are just lists.
We often find such arrays in our lives. Probably the best example of this is a chessboard.
A chessboard is composed of rows and columns. There are eight rows and eight columns.
Each column is marked with the letters A through H. Each line is marked with a number
from one to eight.
Juniper
Business
Use Only
The location of each field is identified by letter-digit pairs. Thus, we know that the bottom
left corner of the board (the one with the white rook) is A1, while the opposite corner is H8.
Let's assume that we're able to use the selected numbers to represent any chess piece. We
can also assume that every row on the chessboard is a list.
row = []
for i in range(8):
row.append(WHITE_PAWN)
It builds a list containing eight elements representing the second row of the chessboard -
the one filled with pawns (assume that WHITE_PAWN is a predefined symbol representing a
white pawn).
The same effect may be achieved by means of a list comprehension, the special syntax
used by Python in order to fill massive lists.
Example #1:
Juniper
Business
Use Only
squares = [x ** 2 for x in range(10)]
The snippet produces a ten-element list filled with squares of ten integer numbers starting
from zero (0, 1, 4, 9, 16, 25, 36, 49, 64, 81)
Example #2:
The snippet creates an eight-element array containing the first eight powers of two (1, 2, 4,
8, 16, 32, 64, 128)
Example #3:
The snippet makes a list with only the odd elements of the squares list.
So, if we want to create a list of lists representing the whole chessboard, it may be done in
the following way:
board = []
for i in range(8):
row = [EMPTY for i in range(8)]
board.append(row)
Note:
the inner part of the loop creates a row consisting of eight elements (each of them
equal to EMPTY ) and appends it to the board list;
the outer part repeats it eight times;
Juniper
Business
Use Only
in total, the board list consists of 64 elements (all equal to EMPTY )
This model perfectly mimics the real chessboard, which is in fact an eight-element list of
elements, all being single rows. Let's summarize our observations:
the elements of the rows are fields, eight of them per row;
the elements of the chessboard are rows, eight of them per chessboard.
The board variable is now a two-dimensional array. It's also called, by analogy to algebraic
terms, a matrix.
As list comprehensions can be nested, we can shorten the board creation in the following
way:
The inner part creates a row, and the outer part builds a list of rows.
Take a look at the chessboard. Every field contains a pair of indices which should be given to
access the field's content:
Juniper
Business
Use Only
Glancing at the figure shown above, let's set some chess pieces on the board. First, let's add
all the rooks:
Juniper
Business
Use Only
And now a pawn to E5:
for i in range(8):
row = [EMPTY for i in range(8)]
board.append(row)
board[0][0] = ROOK
board[0][7] = ROOK
board[7][0] = ROOK
board[7][7] = ROOK
pprint(board)
Imagine that you develop a piece of software for an automatic weather station. The device
records the air temperature on an hourly basis and does it throughout the month. This gives
you a total of 24 × 31 = 744 values. Let's try to design a list capable of storing all these
results.
Juniper
Business
Use Only
First, you have to decide which data type would be adequate for this application. In this
case, a float would be best, since this thermometer is able to measure the temperature
with an accuracy of 0.1 ℃.
Then you take an arbitrary decision that the rows will record the readings every hour on the
hour (so the row will have 24 elements) and each of the rows will be assigned to one day of
the month (let's assume that each month has 31 days, so you need 31 rows). Here's the
appropriate pair of comprehensions ( h is for hour, d for day):
The whole matrix is filled with zeros now. You can assume that it's updated automatically
using special hardware agents. The thing you have to do is to wait for the matrix to be filled
with measurements.
Now it's time to determine the monthly average noon temperature. Add up all 31 readings
recorded at noon and divide the sum by 31. You can assume that the midnight temperature
is stored first. Here's the relevant code:
total = 0.0
average = total / 31
Note: the day variable used by the for loop is not a scalar - each pass through
the temps matrix assigns it with the subsequent rows of the matrix; hence, it's a list. It has
to be indexed with 11 to access the temperature value measured at noon.
Now find the highest temperature during the whole month - see the code:
Juniper
Business
Use Only
#
# The matrix is magically updated here.
#
highest = -100.0
Note:
the day variable iterates through all the rows in the temps matrix;
the temp variable iterates through all the measurements taken in one day.
Now count the days when the temperature at noon was at least 20 ℃:
hot_days = 0
Three-dimensional arrays
Python does not limit the depth of list-in-list inclusion. Here you can see an example of a
three-dimensional array:
Imagine a hotel. It's a huge hotel consisting of three buildings, 15 floors each. There are 20
rooms on each floor. For this, you need an array which can collect and process information
on the occupied/free rooms.
First step - the type of the array's elements. In this case, a Boolean value ( True / False )
would fit.
Juniper
Business
Use Only
Step two - calm analysis of the situation. Summarize the available information: three
buildings, 15 floors, 20 rooms.
The first index ( 0 through 2 ) selects one of the buildings; the second ( 0 through 14 ) selects
the floor, the third ( 0 through 19 ) selects the room number. All rooms are initially free.
Now you can book a room for two newlyweds: in the second building, on the tenth floor,
room 14:
and release the second room on the fifth floor located in the first building:
Check if there are any vacancies on the 15th floor of the third building:
vacancy = 0
The vacancy variable contains 0 if all the rooms are occupied, or the number of available
rooms otherwise.
Congratulations! You've made it to the end of the module. Keep up the good work!
Juniper
Business
Use Only
Key takeaways
1. List comprehension allows you to create new lists from existing ones in a concise and elegant way. The
syntax of a list comprehension looks as follows:
Here's an example of a list comprehension - the code creates a five-element list filled with with the first
five natural numbers raised to the power of 3:
2. You can use nested lists in Python to create matrices (i.e., two-dimensional lists). For example:
Juniper
Business
Use Only
# A four-column/four-row table - a two dimensional array (4x4)
print (table)
print (table[0][0]) # outputs: ':('
print (table[0][3]) # outputs: ':)'
3. You can nest as many lists in lists as you want, and therefore create n-dimensional lists, e.g., three-,
four- or even sixty-four-dimensional arrays. For example:
Juniper
Business
Use Only
# Cube - a three-dimensional array (3x3x3)
print (cube)
print (cube[0][0][0]) # outputs: ':('
print (cube[2][2][0]) # outputs: ':)'
Juniper
Business
Use Only
Why do we need functions?
You've come across functions many times so far, but the view on their merits that we have given you has
been rather one-sided. You've only invoked the functions by using them as tools to make life easier, and to
simplify time-consuming and tedious tasks.
When you want some data to be printed on the console, you use print() . When you want to read the
value of a variable, you use input() , coupled with either int() or float() .
You've also made use of some methods, which are in fact functions, but declared in a very specific way.
Now you'll learn how to write your own functions, and how to use them. We'll write several functions
together, from the very simple to the rather complex, which will require your focus and attention.
It often happens that a particular piece of code is repeated many times in your program. It's repeated
either literally, or with only a few minor modifications, consisting of the use of other variables in the same
algorithm. It also happens that a programmer cannot resist simplifying the work, and begins to clone such
pieces of code using the clipboard and copy-paste operations.
It could end up as greatly frustrating when suddenly it turns out that there was an error in the cloned code.
The programmer will have a lot of drudgery to find all the places that need corrections. There's also a high
risk of the corrections causing errors.
We can now define the first condition which can help you decide when to start writing your own
functions: if a particular fragment of the code begins to appear in more than one place, consider the
possibility of isolating it in the form of a function invoked from the points where the original code was
placed before.
It may happen that the algorithm you're going to implement is so complex that your code begins to grow in
an uncontrolled manner, and suddenly you notice that you're not able to navigate through it so easily
anymore.
You can try to cope with the issue by commenting the code extensively, but soon you find that this
dramatically worsens your situation - too many comments make the code larger and harder to read.
Some say that a well-written function should be viewed entirely in one glance.
A good and attentive developer divides the code (or more accurately: the problem) into well-isolated
pieces, and encodes each of them in the form of a function.
Juniper
Business
Use Only
This considerably simplifies the work of the program, because each piece of code can be encoded
separately, and tested separately. The process described here is often called decomposition.
We can now state the second condition: if a piece of code becomes so large that reading and
understating it may cause a problem, consider dividing it into separate, smaller problems, and
implement each of them in the form of a separate function.
This decomposition continues until you get a set of short functions, easy to understand and test.
Decomposition
It often happens that the problem is so large and complex that it cannot be assigned to a single developer,
and a team of developers have to work on it. The problem must be split between several developers in a
way that ensures their efficient and seamless cooperation.
Juniper
Business
Use Only
It seems inconceivable that more than one programmer should write the same piece of code at the same
time, so the job has to be dispersed among all the team members.
This kind of decomposition has a different purpose to the one described previously - it's not only
about sharing the work, but also about sharing the responsibility among many developers.
Each of them writes a clearly defined and described set of functions, which when combined into the
module (we'll tell you about this a bit later) will give the final product.
This leads us directly to the third condition: if you're going to divide the work among multiple
programmers, decompose the problem to allow the product to be implemented as a set of separately
written functions packed together in different modules.
Juniper
Business
Use Only
Where do the functions come from?
In general, functions come from at least three places:
from Python itself - numerous functions (like print() ) are an integral part of Python, and are
always available without any additional effort on behalf of the programmer; we call these
functions built-in functions;
from Python's preinstalled modules - a lot of functions, very useful ones, but used significantly
less often than built-in ones, are available in a number of modules installed together with Python;
the use of these functions requires some additional steps from the programmer in order to make
them fully accessible (we'll tell you about this in a while);
directly from your code - you can write your own functions, place them inside your code, and
use them freely;
there is one other possibility, but it's connected with classes, so we'll omit it for now.
It's rather simple, but we only want it to be an example of transforming a repeating part
of a code into a function.
The messages sent to the console by the print() function are always the same. Of course,
there's nothing really bad in such a code, but try to imagine what you would have to do if
your boss asked you to change the message to make it more polite, e.g., to start it with the
phrase "Please," .
It seems that you'd have to spend some time changing all the occurrences of the message
(you'd use a clipboard, of course, but it wouldn't make your life much easier). It's obvious
Juniper
Business
Use Only
that you'd probably make some mistakes during the amendment process, and you (and
your boss) would get a bit frustrated.
Is it possible to separate such a repeatable part of the code, name it and make it reusable? It
would mean that a change made once in one place would be propagated to all the
places where it's used.
Of course, such a code should work only when it's explicitly launched.
def function_name():
function_body
We're ready to define our prompting function. We'll name it message - here it is:
def message():
print("Enter a value: ")
Juniper
Business
Use Only
The function is extremely simple, but fully usable. We've named it message , but you can
label it according to your taste. Let's use it.
def message():
print("Enter a value: ")
Note: we don't use the function at all - there's no invocation of it inside the code.
We start here.
We end here.
output
This means that Python reads the function's definitions and remembers them, but won't
launch any of them without your permission.
We've modified the code now - we've inserted the function's invocation between the start
and end messages:
def message():
print("Enter a value: ")
We start here.
Juniper
Business
Use Only
Enter a value:
We end here.
output
when you invoke a function, Python remembers the place where it happened and jumps into the
invoked function;
the body of the function is then executed;
reaching the end of the function forces Python to return to the place directly after the point of
invocation.
There are two, very important, catches. Here's the first of them:
You mustn't invoke a function which is not known at the moment of invocation.
Remember - Python reads your code from top to bottom. It's not going to look ahead in order to find a
function you forgot to put in the right place ("right" means "before invocation".)
Juniper
Business
Use Only
We've inserted an error into this code - can you see the difference?
def message():
print("Enter a value: ")
We've moved the function to the end of the code. Is Python able to find it when the execution reaches the
invocation?
output
Don't try to force Python to look for functions you didn't deliver at the right time.
def message():
print("Enter a value: ")
message = 1
Assigning a value to the name message causes Python to forget its previous role. The function
named message becomes unavailable.
Fortunately, you're free to mix your code with functions - you're not obliged to put all your functions at
the top of your source file.
Juniper
Business
Use Only
print ("We start here.")
def message():
print("Enter a value: ")
message ()
It may look strange, but it's completely correct, and works as intended.
Let's return to our primary example, and employ the function for the right job, like here:
def message():
print("Enter a value: ")
message ()
a = int(input())
message ()
b = int(input())
message ()
c = int(input())
Modifying the prompting message is now easy and clear - you can do it by changing the code in just one
place - inside the function's body.
Key takeaways
1. A function is a block of code that performs a specific task when the function is called (invoked). You
can use functions to make your code reusable, better organized, and more readable. Functions can have
parameters and return values.
built-in functions which are an integral part of Python (such as the print() function). You can
see a complete list of Python built-in functions at https://docs.python.org/3/library/functions.html.
Juniper
Business
Use Only
the ones that come from pre-installed modules (you'll learn about them in the Python Essentials
2 course)
user-defined functions which are written by users for users - you can write your own functions
and use them freely in your code,
the lambda functions (you'll learn about them in the Python Essentials 2 course.)
3. You can define your own function using the def keyword and the following syntax:
You can define a function which doesn't take any arguments, e.g.:
You can define a function which takes arguments, too, just like the one-parameter function below:
We'll tell you more about parametrized functions in the next section. Don't worry.
Exercise 1
a) user-defined function
b) built-in function
Check
Juniper
Business
Use Only
b - it's a built-in function
Exercise 2
What happens when you try to invoke a function before you define it? Example:
hi()
def hi():
print("hi!")
Check
Exercise 3
def hi():
print("hi")
hi(5)
Check
An exception will be thrown (the TypeError exception to be more precise) - the hi() function doesn't
take any arguments
Parameterized functions
The function's full power reveals itself when it can be equipped with an interface that is able to accept data
provided by the invoker. Such data can modify the function's behavior, making it more flexible and
adaptable to changing conditions.
A parameter is actually a variable, but there are two important factors that make parameters different and
special:
parameters exist only inside functions in which they have been defined, and the only place
where the parameter can be defined is a space between a pair of parentheses in the def statement;
Juniper
Business
Use Only
assigning a value to the parameter is done at the time of the function's invocation, by
specifying the corresponding argument.
def function(parameter):
###
Don't forget:
Let's enrich the function above with just one parameter - we're going to use it to show the user the number
of a value the function asks for.
def message(number):
###
The definition specifies that our function operates on just one parameter named number . You can use it as
an ordinary variable, but only inside the function - it isn't visible anywhere else.
def message(number):
print("Enter a number:", number)
We've made use of the parameter. Note: we haven't assigned the parameter with any value. Is it correct?
Yes, it is.
A value for the parameter will arrive from the function's environment.
Juniper
Business
Use Only
Remember: specifying one or more parameters in a function's definition is also a requirement, and you
have to fulfil it during invocation. You must provide as many arguments as there are defined
parameters.
output
def message(number):
print("Enter a number:", number)
message(1)
Moreover, it behaves better. The code will produce the following output:
Enter a number: 1
output
Can you see how it works? The value of the argument used during invocation ( 1 ) has been
passed into the function, setting the initial value of the parameter named number .
It's legal, and possible, to have a variable named the same as a function's parameter.
Juniper
Business
Use Only
def message(number):
print("Enter a number:", number)
number = 1234
message(1)
print(number)
The parameter named number is a completely different entity from the variable
named number .
This means that the snippet above will produce the following output:
Enter a number: 1
1234
output
This also means that invoking the function will require two arguments.
The first new parameter is intended to carry the name of the desired value.
Here it is:
Juniper
Business
Use Only
def message(what, number):
print("Enter", what, "number", number)
output
Run the code, modify it, add more parameters, and see how this affects the output.
You've used it already, but Python can offer a lot more. We're going to tell you about it now.
my_function (1, 2, 3)
Note: positional parameter passing is intuitively used by people in many social occasions.
For example, it may be generally accepted that when we introduce ourselves we mention
our first name(s) before our last name, e.g., "My name's John Doe."
Juniper
Business
Use Only
Let's implement that social custom in Python. The following function will be responsible for
introducing somebody:
Can you guess the output? Run the code and find out if you were right.
Now imagine that the same function is being used in Hungary. In this case, the code would
look like this:
def introduction(first_name, last_name):
print("Hello, my name is", first_name, last_name)
Run the code to see if you were right here, too. Are you surprised?
Juniper
Business
Use Only
The concept is clear - the values passed to the parameters are preceded by the target
parameters' names, followed by the = sign.
The position doesn't matter here - each argument's value knows its destination on the basis
of the name used.
You should be able to predict the output. Run the code to check if you were right.
introduction(surname="Skywalker", first_name="Luke")
output
To show you how it works, we'll use the following simple three-parameter function:
Juniper
Business
Use Only
Its purpose is to evaluate and present the sum of all its arguments.
adding (1, 2, 3)
will output:
1 + 2 + 3 = 6
output
Of course, you can replace such an invocation with a purely keyword variant, like this:
adding (c = 1, a = 2, b = 3)
2 + 3 + 1 = 6
output
adding (3, c = 1, b = 2)
Juniper
Business
Use Only
Let's analyze it:
the argument ( 3 ) for the a parameter is passed using the positional way;
the arguments for c and b are specified as keyword ones.
3 + 2 + 1 = 6
output
Be careful, and beware of mistakes. If you try to pass more than one value to one argument,
all you'll get is a runtime error.
Look at the invocation below - it seems that we've tried to set a twice:
adding(3, a = 1, b = 2)
Python's response:
output
Look at the snipet below. A code like this is fully correct, but it doesn't make much sense:
adding (4, 3, c = 2)
Everything is right, but leaving in just one keyword argument looks a bit weird - what do you
think?
Juniper
Business
Use Only
It happens at times that a particular parameter's values are in use more often than others.
Such arguments may have their default (predefined) values taken into consideration when
their corresponding arguments have been omitted.
They say that the most popular English last name is Smith. Let's try to take this into account.
The default parameter's value is set using clear and pictorial syntax:
You only have to extend the parameter's name with the = sign, followed by the default
value.
Can you guess the output of the program? Run it and check if you were right.
And? Everything looks the same, but when you invoke the function in a way that looks a bit
suspicious at first sight, like this:
introduction ("Henry")
or this:
introduction (first_name="William")
there will be no error, and both invocations will succeed, while the console will show the
following output:
output
Juniper
Business
Use Only
Test it.
You can go further if it's useful. Both parameters have their default values now, look at the
code below:
introduction ()
output
If you use one keyword argument, the remaining one will take the default value:
introduction (last_name="Hopkins")
output
Test it.
Juniper
Business
Use Only
Congratulations - you have just learned the basic ways of communicating with functions.
Key takeaways
1. You can pass information to functions by using parameters. Your functions can have as many
parameters as you need.
def hi(name):
print("Hi,", name)
hi ("Greg")
s = input("Street: ")
p_c = input("Postal Code: ")
c = input("City: ")
positional argument passing in which the order of arguments passed matters (Ex. 1),
keyword (named) argument passing in which the order of arguments passed doesn't matter (Ex.
2),
a mix of positional and keyword argument passing (Ex. 3).
Ex . 1
Juniper
Business
Use Only
def subtra(a, b):
print(a - b)
Ex . 2
def subtra(a, b):
print(a - b)
Ex . 3
def subtra(a, b):
print(a - b)
It's important to remember that positional arguments mustn't follow keyword arguments. That's why if
you try to run the following snippet:
3. You can use the keyword argument passing technique to pre-define a value for a given argument:
Juniper
Business
Use Only
Exercise 1
intro()
Check
Exercise 2
intro(b="Sean Connery")
Check
Exercise 3
intro("Susan")
Check
Juniper
Business
Use Only
Exercise 4
add_numbers(a=1, c=3)
Check
To get functions to return a value (but not only for this purpose) you use the return instruction.
This word gives you a full picture of its capabilities. Note: it's a Python keyword.
The return instruction has two different variants - let's consider them separately.
return without an expression
The first consists of the keyword itself, without anything following it.
When used inside a function, it causes the immediate termination of the function's execution, and an
instant return (hence the name) to the point of invocation.
Note: if a function is not intended to produce a result, using the return instruction is not obligatory - it
will be executed implicitly at the end of the function.
Anyway, you can use it to terminate a function's activities on demand, before the control reaches the
function's last line.
Juniper
Business
Use Only
Let's consider the following function:
happy_new_year ()
The function causes a little noise - the output will look like this:
Three...
Two...
One...
Happy New Year!
output
happy_new_year (False)
will modify the function's behavior - the return instruction will cause its termination just before the
wishes - this is the updated output:
Three...
Two...
One...
output
Juniper
Business
Use Only
return with an expression
The second return variant is extended with an expression:
def function():
return expression
def boring_function():
return 123
x = boring_function()
Juniper
Business
Use Only
The return instruction, enriched with the expression (the expression is very simple here), "transports"
the expression's value to the place where the function has been invoked.
Note, we're not being too polite here - the function returns a value, and we ignore it (we don't use it in any
way):
def boring_function():
print("'Boredom Mode' ON.")
return 123
output
Juniper
Business
Use Only
The only disadvantage is that the result has been irretrievably lost.
Don't forget:
you are always allowed to ignore the function's result, and be satisfied with the function's effect
(if the function has any)
if a function is intended to return a useful result, it must contain the second variant of
the return instruction.
Wait a minute - does this mean that there are useless results, too? Yes - in some sense.
Its data doesn't represent any reasonable value - actually, it's not a value at all; hence,
it mustn't take part in any expressions.
print(None + 2)
output
There are only two kinds of circumstances when None can be safely used:
value = None
if value is None:
print("Sorry, you don't carry any value")
Juniper
Business
Use Only
Don't forget this: if a function doesn't return a certain value using a return expression
clause, it is assumed that it implicitly returns None .
def a():
print("Returning None")
x = a()
print(x)
Returning None
None
It's obvious that the strangeFunction function returns True when its argument is even.
def strange_function(n):
if(n % 2 == 0):
return True
print (strange_function(2))
print (strange_function(1))
True
None
output
Juniper
Business
Use Only
Don't be surprised next time you see None as a function result - it may be the symptom of a
subtle mistake inside the function.
Of course it may! Any entity recognizable by Python can play the role of a function
argument, although it has to be assured that the function is able to cope with it.
So, if you pass a list to a function, the function has to handle it like a list.
def list_sum(lst):
s = 0
return s
will return 12 as a result, but you should expect problems if you invoke it in this risky way:
print(list_sum(5))
output
Juniper
Business
Use Only
This is caused by the fact that a single integer value mustn't be iterated through by
the for loop.
Look at the code in the editor. The program's output will be like this:
[4, 3, 2, 1, 0]
output
Let's dive a little deeper into the issues connected with variables in functions. This is
essential for creating effective and safe functions.
def strange_list_fun(n):
strange_list = []
return strange_list
print(strange_list_fun(5))
Estimated time
10-15 minutes
Level of difficulty
Easy
Juniper
Business
Use Only
Objectives
Familiarize the student with:
Scenario
Your task is to write and test a function which takes one argument (a year) and
returns True if the year is a leap year, or False otherwise.
The seed of the function is already sown in the skeleton code in the editor.
Note: we've also prepared a short testing code, which you can use to test your function.
The code uses two lists - one with the test data, and the other containing the expected
results. The code will tell you if any of your results are invalid.
def is_year_leap(year):
if year % 4 != 0:
return False
elif year % 100 != 0:
return True
elif year % 400 != 0:
return False
else:
return True
1900 ->OK
2000 ->OK
2016 ->OK
1987 ->OK
Estimated time
15-20 minutes
Juniper
Business
Use Only
Level of difficulty
Medium
Prerequisites
LAB 4.3.1.6
Objectives
Familiarize the student with:
Scenario
Your task is to write and test a function which takes two arguments (a year and a month)
and returns the number of days for the given month/year pair (while only February is
sensitive to the year value, your function should be universal).
The initial part of the function is ready. Now, convince the function to return None if its
arguments don't make sense.
Of course, you can (and should) use the previously written and tested function (LAB 4.3.1.6).
It may be very helpful. We encourage you to use a list filled with the months' lengths. You
can create it inside the function - this trick will significantly shorten the code.
def is_year_leap(year):
if year % 4 != 0:
return False
elif year % 100 != 0:
return True
elif year % 400 != 0:
return False
else:
return True
Juniper
Business
Use Only
print("Incorrect entry")
exit()
elif month in [4,6,9,11]:
return 30
else:
return 31
1900 2 ->OK
2000 2 ->OK
2016 1 ->OK
1987 11 ->OK
Estimated time
20-30 minutes
Level of difficulty
Medium
Prerequisites
LAB 4.3.1.6
LAB 4.3.1.7
Objectives
Familiarize the student with:
Juniper
Business
Use Only
Scenario
Your task is to write and test a function which takes three arguments (a year, a month, and a
day of the month) and returns the corresponding day of the year, or returns None if any of
the arguments is invalid.
Use the previously written and tested functions. Add some test cases to the code. This test is
only a beginning.
def is_year_leap(year):
if year % 4 != 0:
return False
elif year % 100 != 0:
return True
elif year % 400 != 0:
return False
else:
return True
Juniper
Business
Use Only
for Mn in range(1,Tmon):
Mndays += days_in_month(year, Mn)
for Mn in range(month+1,13):
Mndays += days_in_month(year, Mn)
TotDays = Yrdays + Mndays + Tdate + (days_in_month(year,month)-day)
else:
if month > Tmon:
for Mn in range(Tmon,month+1)
Mndays += days_in_month(year, Mn)
elif Tmon > month:
for Mn in range(month+1,Tmon):
Mndays += days_in_month(year, Mn)
TotDays = Mndays + Tdate + (days_in_month(year,month)-day)
else:
if Tdate > day:
TotDays = Tdate - day
else:
TotDays = day - Tdate
print (TotDays)
print(day_of_year(2021, 6, 10))
Estimated time
15-20 minutes
Level of difficulty
Medium
Objectives
familiarizing the student with classic notions and algorithms;
improving the student's skills in defining and using functions.
Scenario
A natural number is prime if it is greater than 1 and has no divisors other than 1 and itself.
Complicated? Not at all. For example, 8 isn't a prime number, as you can divide it by 2 and 4
(we can't use divisors equal to 1 and 8, as the definition prohibits this).
On the other hand, 7 is a prime number, as we can't find any legal divisors for it.
Juniper
Business
Use Only
The function:
is called is_prime ;
takes one argument (the value to check)
returns True if the argument is a prime number, and False otherwise.
Hint: try to divide the argument by all subsequent values (starting from 2) and check the
remainder - if it's zero, your number cannot be a prime; think carefully about when you
should stop the process.
If you need to know the square root of any value, you can utilize the ** operator.
Remember: the square root of x is the same as x0.5
Run your code and check whether your output is the same as ours.
Expected output
2 3 5 7 11 13 17 19
def is_prime(num):
if num < 4:
return True
else:
for i in range(2,num-1):
if num % i == 0:
return False
return True
2 3 5 7 11 13 17 19
Estimated time
10-15 minutes
Juniper
Business
Use Only
Level of difficulty
Easy
Objectives
improving the student's skills in defining, using and testing functions.
Scenario
A car's fuel consumption may be expressed in many different ways. For example, in Europe,
it is shown as the amount of fuel consumed per 100 kilometers.
In the USA, it is shown as the number of miles traveled by a car using one gallon of fuel.
Your task is to write a pair of functions converting l/100km into mpg, and vice versa.
The functions:
are
named liters_100km_to_miles_gallon and miles_gallon_to_liters_100km re
spectively;
take one argument (the value corresponding to their names)
Run your code and check whether your output is the same as ours.
Expected output
60.31143162393162
31.36194444444444
23.52145833333333
3.9007393587617467
7.490910297239916
10.009131205673757
Key takeaways
Juniper
Business
Use Only
1. You can use the return keyword to tell a function to return some value. The return statement exits
the function, e.g.:
def wishes():
return "Happy Birthday!"
w = wishes()
# Example 1
def wishes():
print("My Wishes")
return "Happy Birthday"
# Example 2
def wishes():
print("My Wishes")
return "Happy Birthday"
print (wishes())
# outputs: My Wishes
# Happy Birthday
Juniper
Business
Use Only
3. You can use a list as a function's argument, e.g.:
def hi_everybody(my_list):
for name in my_list:
print("Hi,", name)
def create_list(n):
my_list = []
for i in range(n):
my_list.append(i)
return my_list
print (create_list(5))
Exercise 1
def hi():
return
print("Hi!")
hi()
Check
Exercise 2
def is_int(data):
if type(data) == int:
return True
Juniper
Business
Use Only
elif type(data) == float:
return False
print(is_int(5))
print(is_int(5.0))
print(is_int("5"))
Check
True
False
None
Exercise 3
def even_num_lst(ran):
lst = []
for num in range(ran):
if num % 2 == 0:
lst.append(num)
return lst
print(even_num_lst(11))
Check
[0, 2, 4, 6, 8, 10]
Exercise 4
def list_updater(lst):
upd_list = []
for elem in lst:
elem **= 2
upd_list.append(elem)
return upd_list
Juniper
Business
Use Only
foo = [1, 2, 3, 4, 5]
print(list_updater(foo))
Check
The scope of a name (e.g., a variable name) is the part of a code where the name is
properly recognizable.
For example, the scope of a function's parameter is the function itself. The parameter is
inaccessible outside the function.
Let's check it. Look at the code in the editor. What will happen when you run it?
The program will fail when run. The error message will read:
output
This is to be expected.
We're going to conduct some experiments with you to show you how Python constructs
scopes, and how you can use its habits to your benefit.
def scope_test():
x = 123
scope_test()
print(x)
Juniper
Business
Use Only
Functions and scopes: continued
Let's start by checking whether or not a variable created outside any function is visible
inside the functions. In other words, does a variable's name propagate into a function's
body?
output
The answer is: a variable existing outside a function has a scope inside the functions'
bodies.
This rule has a very important exception. Let's try to find it.
def my_function():
var = 2
print("Do I know that variable?", var)
var = 1
my_function()
print(var)
The result has changed, too - the code produces a slightly different output now:
output
Juniper
Business
Use Only
What's happened?
the var variable created inside the function is not the same as when defined outside
it - it seems that there two different variables of the same name;
moreover, the function's variable shadows the variable coming from the outside
world.
A variable existing outside a function has a scope inside the functions' bodies,
excluding those of them which define a variable of the same name.
It also means that the scope of a variable existing outside a function is supported only
when getting its value (reading). Assigning a value forces the creation of the function's
own variable.
Make sure you understand this well and carry out your own experiments.
def my_function():
print("Do I know that variable?", var)
var = 1
my_function()
print(var)
There's a special Python method which can extend a variable's scope in a way which
includes the functions' bodies (even if you want not only to read the values, but also to
modify them).
global name
global name1, name2, ...
Juniper
Business
Use Only
Using this keyword inside a function with the name (or names separated with commas) of a
variable(s), forces Python to refrain from creating a new variable inside the function - the
one accessible from outside will be used instead.
In other words, this name becomes global (it has a global scope, and it doesn't matter
whether it's the subject of read or assign).
output
This should be sufficient evidence to show that the global keyword does what it promises.
def my_function():
global var
var = 2
print("Do I know that variable?", var)
var = 1
my_function()
print(var)
The code in the editor should teach you something. As you can see, the function changes
the value of its parameter. Does the change affect the argument?
Juniper
Business
Use Only
Run the program and check.
I got 1
I have 2
1
output
The conclusion is obvious - changing the parameter's value doesn't propagate outside
the function (in any case, not when the variable is a scalar, like in the example).
This also means that a function receives the argument's value, not the argument itself. This
is true for scalars.
Is it worth checking how it works with lists (do you recall the peculiarities of assigning list
slices versus assigning lists as a whole?).
def my_function(my_list_1):
print("Print #1:", my_list_1)
print("Print #2:", my_list_2)
my_list_1 = [0, 1]
print("Print #3:", my_list_1)
print("Print #4:", my_list_2)
my_list_2 = [2, 3]
my_function (my_list_2)
print ("Print #5:", my_list_2)
output
Juniper
Business
Use Only
It seems that the former rule still works.
def my_function(my_list_1):
print("Print #1:", my_list_1)
print("Print #2:", my_list_2)
del my_list_1[0] # Pay attention to this line.
print("Print #3:", my_list_1)
print("Print #4:", my_list_2)
my_list_2 = [2, 3]
my_function (my_list_2)
print ("Print #5:", my_list_2)
We don't change the value of the parameter my_list_1 (we already know it will not affect
the argument), but instead modify the list identified by it.
output
Let's try:
if the argument is a list, then changing the value of the corresponding parameter
doesn't affect the list (remember: variables containing lists are stored in a different
way than scalars),
but if you change a list identified by the parameter (note: the list, not the
parameter!), the list will reflect the change.
It's time to write some example functions. You'll do that in the next section.
Juniper
Business
Use Only
Key takeaways
1. A variable that exists outside a function has a scope inside the function body (Example 1) unless the
function defines a variable of the same name (Example 2, and Example 3), e.g.:
Example 1:
var = 2
def mult_by_var(x):
return x * var
print(mult_by_var(7)) # outputs: 14
Example 2:
def mult(x):
var = 5
return x * var
print(mult(7)) # outputs: 35
Example 3:
def mult(x):
var = 7
return x * var
var = 3
print(mult(7)) # outputs: 49
2. A variable that exists inside a function has a scope inside the function body (Example 4), e.g.:
Example 4:
def adding(x):
Juniper
Business
Use Only
var = 7
return x + var
print(adding(4)) # outputs: 11
print(var) # NameError
3. You can use the global keyword followed by a variable name to make the variable's scope global,
e.g.:
var = 2
print (var) # outputs: 2
def return_var():
global var
var = 5
return var
Exercise 1
What will happen when you try to run the following code?
def message():
alt = 1
print("Hello, World!")
print(alt)
Check
The NameError exception will be thrown ( NameError: name 'alt' is not defined )
Exercise 2
Juniper
Business
Use Only
What is the output of the following snippet?
a = 1
def fun():
a = 2
print(a)
fun()
print(a)
Check
Exercise 3
a = 1
def fun():
global a
a = 2
print(a)
fun()
a = 3
print(a)
Check
Exercise 4
Juniper
Business
Use Only
What is the output of the following snippet?
a = 1
def fun():
global a
a = 2
print(a)
a = 3
fun()
print(a)
Check
It seems that this new function will have two parameters. Its name will be bmi , but if you
prefer any other name, use it instead.
Juniper
Business
Use Only
Let's code the function:
print(bmi(52.5, 1.65))
19.283746556473833
output
The function fulfils our expectations, but it's a bit simple - it assumes that the values of both
parameters are always meaningful. It's definitely worth checking if they're trustworthy.
Let's check them both and return None if any of them looks suspicious.
First, the test invocation ensures that the protection works properly - the output is:
None
output
Second, take a look at the way the backslash ( \ ) symbol is used. If you use it in Python code
and end a line with it, it will tell Python to continue the line of code in the next line of code.
It can be particularly useful when you have to deal with long lines of code and you'd like to
improve code readability.
Juniper
Business
Use Only
Okay, but there's something we omitted too easily - the imperial measurements. This
function is not too useful for people accustomed to pounds, feet and inches.
We can write two simple functions to convert imperial units to metric ones. Let's start
with pounds.
It is a well-known fact that 1 lb = 0.45359237 kg . We'll use this in our new function.
def lb_to_kg(lb):
return lb * 0.45359237
print(lb_to_kg(1))
0.45359237
output
And now it's time for feet and inches: 1 ft = 0.3048 m , and 1 in = 2.54 cm = 0.0254
m.
print(ft_and_inch_to_m(1, 1))
0.3302
output
Juniper
Business
Use Only
It looks as expected.
Note: we wanted to name the second parameter just in , not inch , but we couldn't. Do you
know why?
1.8288000000000002
output
It's quite possible that sometimes you may want to use just feet without inches. Will Python
help you? Of course it will.
print(ft_and_inch_to_m(6))
Now the inch parameter has its default value equal to 0.0 .
1.8288000000000002
output
Juniper
Business
Use Only
Finally, the code is able to answer the question: what is the BMI of a person 5'7" tall and
weighing 176 lbs?
def lb_to_kg(lb):
return lb * 0.45359237
27.565214082533313
output
Juniper
Business
Use Only
We know from school that the sum of two arbitrary sides has to be longer than the third side.
It won't be a hard challenge. The function will have three parameters - one for each side.
It will return True if the sides can build a triangle, and False otherwise. In this
case, is_a_triangle is a good name for such a function.
Look at the code in the editor. You can find our function there. Run the program.
True
False
output
Juniper
Business
Use Only
if a + b <= c or b + c <= a or c + a <= b:
return False
return True
We've negated the condition (reversed the relational operators and replaced or s with and s,
receiving a universal expression for testing triangles).
Let's install the function in a larger program. It'll ask the user for three values and make use
of the function.
In the second step, we'll try to ensure that a certain triangle is a right-angle triangle.
c2 = a2 + b2
Juniper
Business
Use Only
Here is the code:
Look at how we test the relationship between the hypotenuse and the remaining sides - we
choose the longest side, and apply the Pythagorean theorem to check if everything is right.
This requires three checks in total.
Juniper
Business
Use Only
We're going use the exponentiation operator to find the square root - it may seem strange,
but it works:
We try it with a right-angle triangle as a half of a square with one side equal to 1. This means
that its area should be equal to 0.5.
0.49999999999999983
output
It's very close to 0.5, but it isn't exactly 0.5. What does it mean? Is it an error?
Juniper
Business
Use Only
No, it isn't. This is the specifics of floating-point calculations. We'll tell you more about it
soon.
It's marked with an exclamation mark, and is equal to the product of all natural numbers
from one up to its argument.
Let's write our code. We'll create a function and call it factorial_function . Here is the
code:
def factorial_function(n):
if n < 0:
return None
if n < 2:
return 1
product = 1
for i in range(2, n + 1):
product *= i
return product
Notice how we mirror step by step the mathematical definition, and how we use
the for loop to find the product.
We add a simple testing code, and these are the results we get:
1 1
2 2
3 6
4 24
5 120
Juniper
Business
Use Only
output
fib_1 = 1
fib_2 = 1
fib_3 = 1 + 1 = 2
fib_4 = 1 + 2 = 3
fib_5 = 2 + 3 = 5
fib_6 = 3 + 5 = 8
fib_7 = 5 + 8 = 13
Let's create our fib function and test it. Here it is:
def fib(n):
if n < 1:
return None
if n < 3:
return 1
elem_1 = elem_2 = 1
the_sum = 0
for i in range(3, n + 1):
the_sum = elem_1 + elem_2
elem_1, elem_2 = elem_2, the_sum
return the_sum
Analyze the for loop body carefully, and find out how we move
the elem_1 and elem_2 variables through the subsequent Fibonacci numbers.
Juniper
Business
Use Only
The test part of the code produces the following output:
1 -> 1
2 -> 1
3 -> 2
4 -> 3
5 -> 5
6 -> 8
7 -> 13
8 -> 21
9 -> 34
This term may describe many different concepts, but one of them is especially interesting -
the one referring to computer programming.
These two cases seem to be the best to illustrate the phenomenon - factorials and Fibonacci
numbers. Especially the latter.
The Fibonacci numbers definition is a clear example of recursion. We already told you
that:
The definition of the ith number refers to the i-1 number, and so on, till you reach the first
two.
Can it be used in the code? Yes, it can. It can also make the code shorter and clearer.
The second version of our fib() function makes direct use of this definition:
def fib(n):
if n < 1:
return None
if n < 3:
return 1
return fib(n - 1) + fib(n - 2)
Juniper
Business
Use Only
But is it really safe? Does it entail any risk?
Yes, there is a little risk indeed. If you forget to consider the conditions which can stop
the chain of recursive invocations, the program may enter an infinite loop. You have to
be careful.
n! = 1 × 2 × 3 × ... × n-1 × n
n! = (n-1)! × n
Here it is:
def factorial_function(n):
if n < 0:
return None
if n < 2:
return 1
return n * factorial_function(n - 1)
Our short functional journey is almost over. The next section will take care of two curious
Python data types: tuples and dictionaries.
Key takeaways
Juniper
Business
Use Only
1. A function can call other functions or even itself. When a function calls itself, this situation is known
as recursion, and the function which calls itself and contains a specified termination condition (i.e., the
base case - a condition which doesn't tell the function to make any further calls to that function) is called
a recursive function.
2. You can use recursive functions in Python to write clean, elegant code, and divide it into smaller,
organized chunks. On the other hand, you need to be very careful as it might be easy to make a mistake
and create a function which never terminates. You also need to remember that recursive calls consume
a lot of memory, and therefore may sometimes be inefficient.
When using recursion, you need to take all its advantages and disadvantages into consideration.
The factorial function is a classic example of how the concept of recursion can be put in practice:
def factorial(n):
return 1
else:
return n * factorial(n - 1)
print(factorial(4)) # 4 * 3 * 2 * 1 = 24
Exercise 1
What will happen when you attempt to run the following snippet and why?
def factorial(n):
return n * factorial(n - 1)
print(factorial(4))
Juniper
Business
Use Only
Check
The factorial function has no termination condition (no base case) so Python will raise an exception
( RecursionError: maximum recursion depth exceeded )
Exercise 2
def fun(a):
if a > 30:
return 3
else:
return a + fun(a + 3)
print(fun(25))
Check
56
A sequence type is a type of data in Python which is able to store more than one value (or less than
one, as a sequence may be empty), and these values can be sequentially (hence the name) browsed,
element by element.
As the for loop is a tool especially designed to iterate through sequences, we can express the definition
as: a sequence is data which can be scanned by the for loop.
You've encountered one Python sequence so far - the list. The list is a classic example of a Python
sequence, although there are some other sequences worth mentioning, and we're going to present them to
you now.
The second notion - mutability - is a property of any of Python's data that describes its readiness to be
freely changed during program execution. There are two kinds of Python data: mutable and immutable.
Juniper
Business
Use Only
Mutable data can be freely updated at any time - we call such an operation in situ.
In situ is a Latin phrase that translates as literally in position. For example, the following instruction
modifies the data in situ:
list .append(1)
Imagine that a list can only be assigned and read over. You would be able neither to append an element to
it, nor remove any element from it. This means that appending an element to the end of the list would
require the recreation of the list from scratch.
You would have to build a completely new list, consisting of the all elements of the already existing list,
plus the new element.
The data type we want to tell you about now is a tuple. A tuple is an immutable sequence type. It can
behave like a list, but it mustn't be modified in situ.
What is a tuple?
The first and the clearest distinction between lists and tuples is the syntax used to create them - tuples
prefer to use parenthesis, whereas lists like to see brackets, although it's also possible to create a tuple
just from a set of values separated by commas.
tuple_1 = (1, 2, 4, 8)
tuple_2 = 1., .5, .25, .125
tuple_1 = (1, 2, 4, 8)
tuple_2 = 1., .5, .25, .125
print (tuple_1)
print (tuple_2)
Juniper
Business
Use Only
(1, 2, 4, 8)
(1.0, 0.5, 0.25, 0.125)
output
Note: each tuple element may be of a different type (floating-point, integer, or any other not-as-yet-
introduced kind of data).
empty_tuple = ()
If you want to create a one-element tuple, you have to take into consideration the fact that, due to syntax
reasons (a tuple has to be distinguishable from an ordinary, single value), you must end the value with a
comma:
one_element_tuple_1 = (1, )
one_element_tuple_2 = 1.,
Removing the commas won't spoil the program in any syntactical sense, but you will instead get two single
variables, not tuples.
The program should produce the following output - run it and check:
1
1000
(10, 100, 1000)
(1, 10)
Juniper
Business
Use Only
1
10
100
1000
output
The similarities may be misleading - don't try to modify a tuple's contents! It's not a list!
All of these instructions (except the topmost one) will cause a runtime error:
my_tuple.append(10000)
del my_tuple[0]
my_tuple[1] = -10
This is the message that Python will give you in the console window:
List is mutable
>>> a = [1,2,3]
>>> id(a)
4538108032
>>> a[0]=10
>>> id(a)
4538108032
>>> del a[2]
>>> id(a)
4538108032
>>> a.append(5)
>>> id(a)
4538108032
>>> a.insert(0,5)
>>> id(a)
4538108032
>>> a
[5, 10, 2, 5]
>>>
ID never changes
Juniper
Business
Use Only
How to use a tuple: continued
What else can tuples do for you?
the len() function accepts tuples, and returns the number of elements contained
inside;
the + operator can join tuples together (we've shown you this already)
the * operator can multiply tuples, just like lists;
the in and not in operators work in the same way as in lists.
9
(1, 10, 100, 1000, 10000)
(1, 10, 100, 1, 10, 100, 1, 10, 100)
True
True
output
One of the most useful tuple properties is their ability to appear on the left side of the
assignment operator. You saw this phenomenon some time ago, when it was necessary to
find an elegant tool to swap two variables' values.
var = 123
t1 = (1, )
t2 = (2, )
t3 = (3, var)
It shows three tuples interacting - in effect, the values stored in them "circulate"
- t1 becomes t2 , t2 becomes t3 , and t3 becomes t1 .
Note: the example presents one more important fact: a tuple's elements can be variables,
not only literals. Moreover, they can be expressions if they're on the right side of the
assignment operator.
Juniper
Business
Use Only
What is a dictionary?
The dictionary is another Python data structure. It's not a sequence type (but can be easily adapted to
sequence processing) and it is mutable.
To explain what the Python dictionary actually is, it is important to understand that it is literally a
dictionary.
The Python dictionary works in the same way as a bilingual dictionary. For example, you have an
English word (e.g., cat) and need its French equivalent. You browse the dictionary in order to find the
word (you may use different techniques to do that - it doesn't matter) and eventually you get it. Next, you
check the French counterpart and it is (most probably) the word "chat".
In Python's world, the word you look for is named a key . The word you get from the dictionary is called
a value .
each key must be unique - it's not possible to have more than one key of the same value;
a key may be any immutable type of object: it can be a number (integer or float), or even a
string, but not a list;
a dictionary is not a list - a list contains a set of numbered values, while a dictionary holds pairs
of values;
the len() function works for dictionaries, too - it returns the numbers of key-value elements in
the dictionary;
a dictionary is a one-way tool - if you have an English-French dictionary, you can look for French
equivalents of English terms, but not vice versa.
Juniper
Business
Use Only
How to make a dictionary?
If you want to assign some initial pairs to a dictionary, you should use the following syntax:
print (dictionary)
print (phone_numbers)
print (empty_dictionary)
In the first example, the dictionary uses keys and values which are both strings. In the second one, the keys
are strings, but the values are integers. The reverse layout (keys → numbers, values → strings) is also
possible, as well as number-number combination.
The list of pairs is surrounded by curly braces, while the pairs themselves are separated by commas,
and the keys and values by colons.
The first of our dictionaries is a very simple English-French dictionary. The second - a very tiny telephone
directory.
The empty dictionaries are constructed by an empty pair of curly braces - nothing unusual.
The dictionary as a whole can be printed with a single print() invocation. The snippet may produce the
following output:
output
Have you noticed anything surprising? The order of the printed pairs is different than in the initial
assignment. What does that mean?
First of all, it's a confirmation that dictionaries are not lists - they don't preserve the order of their data, as
the order is completely meaningless (unlike in real, paper dictionaries). The order in which a
dictionary stores its data is completely out of your control, and your expectations. That's normal. (*)
NOTE
Juniper
Business
Use Only
(*) In Python 3.6x dictionaries have become ordered collections by default. Your results may vary
depending on what Python version you're using.
print (dictionary['cat'])
print (phone_numbers['Suzy'])
Note:
chat
5557654321
output
And now the most important news: you mustn't use a non-existent key. Trying something
like this:
print (phone_numbers['president'])
Fortunately, there's a simple way to avoid such a situation. The in operator, together with
its companion, not in , can salvage this situation.
Juniper
Business
Use Only
The following code safely searches for some French words:
output
NOTE
When you write a big or lengthy expression, it may be a good idea to keep it vertically
aligned. This is how you can make your code more readable and more programmer-friendly,
e.g.:
# Example 1:
dictionary = {
"cat": "chat",
"dog": "chien",
"horse": "cheval"
}
# Example 2:
phone_numbers = {'boss': 5551234567,
'Suzy': 22657854310
}
No and yes.
Juniper
Business
Use Only
No, because a dictionary is not a sequence type - the for loop is useless with it.
Yes, because there are simple and very effective tools that can adapt any dictionary to
the for loop requirements (in other words, building an intermediate link between the
dictionary and a temporary sequence entity).
The first of them is a method named keys() , possessed by each dictionary. The
method returns an iterable object consisting of all the keys gathered within the
dictionary. Having a group of keys enables you to access the whole dictionary in an easy
and handy way.
output
The sorted() function
Do you want it sorted? Just enrich the for loop to get such a form:
The sorted() function will do its best - the output will look like this:
Juniper
Business
Use Only
How to use a dictionary:
The items() and values() methods
Another way is based on using a dictionary's method named items() . The method returns
tuples (this is the first example where tuples are something more than just an example of
themselves) where each tuple is a key-value pair.
Note the way in which the tuple has been used as a for loop variable.
output
There is also a method named values() , which works similarly to keys() , but returns
values.
As the dictionary is not able to automatically find a key for a given value, the role of this
method is rather limited.
cheval
Juniper
Business
Use Only
chien
chat
We're going to replace the value "chat" with "minou" , which is not very accurate, but it will
work well with our example.
Look:
dictionary['cat'] = 'minou'
print(dictionary)
output
Note: this is very different behavior compared to lists, which don't allow you to assign values
to non-existing indices.
Let's add a new pair of words to the dictionary - a bit weird, but still valid:
dictionary['swan'] = 'cygne'
print(dictionary)
Juniper
Business
Use Only
{'cat': 'chat', 'dog': 'chien', 'horse': 'cheval', 'swan': 'cygne'}
output
EXTRA
You can also insert an item to a dictionary by using the update() method, e.g.:
dictionary.update({"duck": "canard"})
print(dictionary)
Removing a key
Can you guess how to remove a key from a dictionary?
Note: removing a key will always cause the removal of the associated value. Values
cannot exist without their keys.
del dictionary['dog']
print(dictionary)
output
EXTRA
Juniper
Business
Use Only
To remove the last item in a dictionary, you can use the popitem() method:
dictionary.popitem()
print(dictionary) # outputs: {'cat': 'chat', 'dog': 'chien'}
In the older versions of Python, i.e., before 3.6.7, the popitem() method removes a random
item from a dictionary.
line 1: create an empty dictionary for the input data; the student's name is used as a
key, while all the associated scores are stored in a tuple (the tuple may be a
dictionary value - that's not a problem at all)
line 3: enter an "infinite" loop (don't worry, it'll break at the right moment)
line 4: read the student's name here;
line 5-6: if the name is an empty string (), leave the loop;
line 8: ask for one of the student's scores (an integer from the range 0-10)
line 9-10: if the score entered is not within the range from 0 to 10, leave the loop;
line 12-13: if the student's name is already in the dictionary, lengthen the associated
tuple with the new score (note the += operator)
line 14-15: if this is a new student (unknown to the dictionary), create a new entry -
its value is a one-element tuple containing the entered score;
line 17: iterate through the sorted students' names;
Juniper
Business
Use Only
line 18-19: initialize the data needed to evaluate the average (sum and counter)
line 20-22: we iterate through the tuple, taking all the subsequent scores and
updating the sum, together with the counter;
line 23: evaluate and print the student's name and average score.
school_class = {}
while True:
name = input("Enter the student's name: ")
if name == '':
break
if name in school_class:
school_class[name] += (score,)
else:
school_class[name] = (score,)
Juniper
Business
Use Only
1. Tuples are ordered and unchangeable (immutable) collections of data. They can be thought of as
immutable lists. They are written in round brackets:
my_tuple = (1, 2, True, "a string", (3, 4), [5, 6], None)
print (my_tuple)
my_list = [1, 2, True, "a string", (3, 4), [5, 6], None]
print (my_list)
Each tuple element may be of a different type (i.e., integers, strings, booleans, etc.). What is more, tuples
can contain other tuples or lists (and the other way round).
empty_tuple = ()
print(type(empty_tuple)) # outputs: <class 'tuple'>
If you remove the comma, you will tell Python to create a variable, not a tuple:
my_tuple_1 = 1,
print (type(my_tuple_1)) # outputs: <class 'tuple'>
Juniper
Business
Use Only
5. Tuples are immutable, which means you cannot change their elements (you cannot append tuples, or
modify, or remove tuple elements). The following snippet will cause an exception:
my_tuple = 1, 2, 3,
del my_tuple
print (my_tuple) # NameError: name 'my_tuple' is not defined
6. You can loop through a tuple elements (Example 1), check if a specific element is (not)present in a tuple
(Example 2), use the len() function to check how many elements there are in a tuple (Example 3), or
even join/multiply tuples (Example 4):
# Example 1
tuple_1 = (1, 2, 3)
for elem in tuple_1:
print(elem)
# Example 2
tuple_2 = (1, 2, 3, 4)
print (5 in tuple_2)
print (5 not in tuple_2)
# Example 3
tuple_3 = (1, 2, 3, 5)
print (len(tuple_3))
# Example 4
tuple_4 = tuple_1 + tuple_2
tuple_5 = tuple_3 * 2
print (tuple_4)
print (tuple_5)
EXTRA
Juniper
Business
Use Only
You can also create a tuple using a Python built-in function called tuple() . This is particularly useful
when you want to convert a certain iterable (e.g., a list, range, string, etc.) to a tuple:
my_list = [2, 4, 6]
print (my_list) # outputs: [2, 4, 6]
print (type(my_list)) # outputs: <class 'list'>
tup = tuple(my_list)
print (tup) # outputs: (2, 4, 6)
print (type(tup)) # outputs: <class 'tuple'>
By the same fashion, when you want to convert an iterable to a list, you can use a Python built-in function
called list() :
tup = 1, 2, 3,
my_list = list(tup)
print (type(my_list)) # outputs: <class 'list'>
1. Dictionaries are unordered*, changeable (mutable), and indexed collections of data. (*In Python 3.6x
dictionaries have become ordered by default.
Each dictionary is a set of key: value pairs. You can create it by using the following syntax:
my_dictionary = {
key1: value1,
key2: value2,
key3: value3,
}
2. If you want to access a dictionary item, you can do so by making a reference to its key inside a pair of
square brackets (ex. 1) or by using the get() method (ex. 2):
pol_eng_dictionary = {
"kwiat": "flower",
"woda": "water",
Juniper
Business
Use Only
"gleba": "soil"
}
item_2 = pol_eng_dictionary.get("woda")
print (item_2) # outputs: water
3. If you want to change the value associated with a specific key, you can do so by referring to the item's
key name in the following way:
pol_eng_dictionary = {
"zamek": "castle",
"woda": "water",
"gleba": "soil"
}
4. To add or remove a key (and the associated value), use the following syntax:
del phonebook["Adam"]
print (phonebook) # outputs: {}
You can also insert an item to a dictionary by using the update() method, and remove the last element
by using the popitem() method, e.g.:
pol_eng_dictionary .popitem()
print (pol_eng_dictionary) # outputs: {'kwiat': 'flower'}
Juniper
Business
Use Only
5. You can use the for loop to loop through a dictionary, e.g.:
pol_eng_dictionary = {
"zamek": "castle",
"woda": "water",
"gleba": "soil"
}
# outputs: zamek
# woda
# gleba
6. If you want to loop through a dictionary's keys and values, you can use the items() method, e.g.:
pol_eng_dictionary = {
"zamek": "castle",
"woda": "water",
"gleba": "soil"
}
7. To check if a given key exists in a dictionary, you can use the in keyword:
pol_eng_dictionary = {
"zamek": "castle",
"woda": "water",
"gleba": "soil"
}
if "zamek" in pol_eng_dictionary:
print("Yes")
else :
print("No")
Juniper
Business
Use Only
8. You can use the del keyword to remove a specific item, or delete a dictionary. To remove all the
dictionary's items, you need to use the clear() method:
pol_eng_dictionary = {
"zamek": "castle",
"woda": "water",
"gleba": "soil"
}
pol_eng_dictionary = {
"zamek": "castle",
"woda": "water",
"gleba": "soil"
}
copy_dictionary = pol_eng_dictionary.copy()
Exercise 1
my_tup = (1, 2, 3)
print(my_tup[2])
Juniper
Business
Use Only
Check
Exercise 2
tup = 1, 2, 3
a, b, c = tup
print(a * b * c)
Check
The program will print 6 to the screen. The tup tuple elements have been "unpacked" in the a , b ,
and c variables.
Exercise 3
Complete the code to correctly use the count() method to find the number of duplicates of 2 in the
following tuple.
tup = 1, 2, 3, 2, 4, 5, 6, 2, 7, 2, 8, 9
duplicates = # Write your code here.
print(duplicates) # outputs: 4
Check
tup = 1, 2, 3, 2, 4, 5, 6, 2, 7, 2, 8, 9
duplicates = tup.count(2)
print(duplicates) # outputs: 4
Juniper
Business
Use Only
Exercise 4
Write a program that will "glue" the two dictionaries ( d1 and d2 ) together and create a new one ( d3 ).
print(d3)
Check
Exercise 5
Check
Sample solution:
my_list = ["car", "Ford", "flower", "Tulip"]
t = tuple(my_list)
print(t)
Exercise 6
Juniper
Business
Use Only
# Write your code here.
print(colors_dictionary)
Check
Sample solution:
colors = (("green", "#008000"), ("blue", "#0000FF"))
colors_dictionary = dict(colors)
print(colors_dictionary)
Exercise 7
print(copy_my_dictionary)
Check
Exercise 8
colors = {
"white": (255, 255, 255),
"grey": (128, 128, 128),
"red": (255, 0, 0),
"green": (0, 128, 0)
}
Juniper
Business
Use Only
Check
red : (255, 0, 0)
Estimated time
30-120 minutes
Level of difficulty
Medium/Hard
Objectives
perfecting the student's skills in using Python for solving complex problems,
integration of programming techniques in one program consisting of many various
parts.
Scenario
Your task is to write a simple program which pretends to play tic-tac-toe with the user.
To make it all easier for you, we've decided to simplify the game. Here are our assumptions:
the computer (i.e., your program) should play the game using 'X' s;
the user (e.g., you) should play the game using 'O' s;
the first move belongs to the computer - it always puts its first 'X' in the middle of
the board;
all the squares are numbered row by row starting with 1 (see the example session
below for reference)
the user inputs their move by entering the number of the square they choose - the
number must be valid, i.e., it must be an integer, it must be greater than 0 and less
than 10 , and it cannot point to a field which is already occupied;
the program checks if the game is over - there are four possible verdicts: the game
should continue, or the game ends with a tie, your win, or the computer's win;
the computer responds with its move and the check is repeated;
don't implement any form of artificial intelligence - a random field choice made by
the computer is good enough for the game.
Juniper
Business
Use Only
The example session with the program may look as follows:
+-------+-------+-------+
| | | |
| 1 | 2 | 3 |
| | | |
+-------+-------+-------+
| | | |
| 4 | X | 6 |
| | | |
+-------+-------+-------+
| | | |
| 7 | 8 | 9 |
| | | |
+-------+-------+-------+
Enter your move: 1
+-------+-------+-------+
| | | |
| O | 2 | 3 |
| | | |
+-------+-------+-------+
| | | |
| 4 | X | 6 |
| | | |
+-------+-------+-------+
| | | |
| 7 | 8 | 9 |
| | | |
+-------+-------+-------+
+-------+-------+-------+
| | | |
| O | X | 3 |
| | | |
+-------+-------+-------+
| | | |
| 4 | X | 6 |
| | | |
+-------+-------+-------+
| | | |
| 7 | 8 | 9 |
| | | |
+-------+-------+-------+
Enter your move: 8
+-------+-------+-------+
| | | |
| O | X | 3 |
| | | |
+-------+-------+-------+
| | | |
| 4 | X | 6 |
| | | |
Juniper
Business
Use Only
+-------+-------+-------+
| | | |
| 7 | O | 9 |
| | | |
+-------+-------+-------+
+-------+-------+-------+
| | | |
| O | X | 3 |
| | | |
+-------+-------+-------+
| | | |
| 4 | X | X |
| | | |
+-------+-------+-------+
| | | |
| 7 | O | 9 |
| | | |
+-------+-------+-------+
Enter your move: 4
+-------+-------+-------+
| | | |
| O | X | 3 |
| | | |
+-------+-------+-------+
| | | |
| O | X | X |
| | | |
+-------+-------+-------+
| | | |
| 7 | O | 9 |
| | | |
+-------+-------+-------+
+-------+-------+-------+
| | | |
| O | X | X |
| | | |
+-------+-------+-------+
| | | |
| O | X | X |
| | | |
+-------+-------+-------+
| | | |
| 7 | O | 9 |
| | | |
+-------+-------+-------+
Enter your move: 7
+-------+-------+-------+
| | | |
| O | X | X |
| | | |
+-------+-------+-------+
| | | |
Juniper
Business
Use Only
| O | X | X |
| | | |
+-------+-------+-------+
| | | |
| O | O | 9 |
| | | |
+-------+-------+-------+
You won!
Requirements
Implement the following features:
the board should be stored as a three-element list, while each element is another
three-element list (the inner lists represent rows) so that all of the squares may be
accessed using the following syntax:
board[row][column]
each of the inner list's elements can contain 'O' , 'X' , or a digit representing the
square's number (such a square is considered free)
the board's appearance should be exactly the same as the one presented in the
example.
implement the functions defined for you in the editor.
Note: the from-import instruction provides an access to the randrange function defined
within an external Python module callled random .
for i in range(10):
print(randrange(8))
Juniper
Business
Use Only
Python Essentials 2:
Module 1
Modules, Packages and PIP
What is a module?
Computer code has a tendency to grow. We can say that code that doesn't grow is probably completely
unusable or abandoned. A real, wanted, and widely used code develops continuously, as both users'
demands and users' expectations develop in their own rhythms.
A code which is not able to respond to users' needs will be forgotten quickly, and instantly replaced with a
new, better, and more flexible code. Be prepared for this, and never think that any of your programs is
eventually completed. The completion is a transition state and usually passes quickly, after the first bug
report. Python itself is a good example how the rule acts.
Growing code is in fact a growing problem. A larger code always means tougher maintenance. Searching
for bugs is always easier where the code is smaller (just as finding a mechanical breakage is simpler when
the machinery is simpler and smaller).
Moreover, when the code being created is expected to be really big (you can use a total number of source
lines as a useful, but not very accurate, measure of a code's size) you may want (or rather, you will be
forced) to divide it into many parts, implemented in parallel by a few, a dozen, several dozen, or even
several hundred individual developers.
Of course, this cannot be done using one large source file, which is edited by all programmers at the same
time. This will surely lead to a spectacular disaster.
Juniper
Business
Use Only
If you want such a software project to be completed successfully, you have to have the means allowing you
to:
For example, a certain project can be divided into two main parts:
the user interface (the part that communicates with the user using widgets and a graphical screen)
the logic (the part processing data and producing results)
Each of these parts can be (most likely) divided into smaller ones, and so on. Such a process is often
called decomposition.
For example, if you were asked to arrange a wedding, you wouldn't do everything yourself - you would
find a number of professionals and split the task between them all.
How do you divide a piece of software into separate but cooperating parts? This is the
question. Modules are the answer.
Juniper
Business
Use Only
the first (probably the most common) happens when you want to use an already existing module,
written by someone else, or created by yourself during your work on some complex project - in
this case you are the module's user;
the second occurs when you want to create a brand new module, either for your own use, or to
make other programmers' lives easier - you are the module's supplier.
First of all, a module is identified by its name. If you want to use any module, you need to know the name.
A (rather large) number of modules is delivered together with Python itself. You can think of them as a
kind of "Python extra equipment".
All these modules, along with the built-in functions, form the Python standard library - a special sort of
library where modules play the roles of books (we can even say that folders play the roles of shelves). If
Juniper
Business
Use Only
you want to take a look at the full list of all "volumes" collected in that library, you can find it
here: https://docs.python.org/3/library/index.html.
Each module consists of entities (like a book consists of chapters). These entities can be functions,
variables, constants, classes, and objects. If you know how to access a particular module, you can make use
of any of the entities it stores.
Let's start the discussion with one of the most frequently used modules, named math . Its name speaks for
itself - the module contains a rich collection of entities (not only functions) which enable a programmer to
effectively implement calculations demanding the use of mathematical functions, like sin() or log().
Importing a module
To make a module usable, you must import it (think of it like of taking a book off the shelf). Importing a
module is done by an instruction named import . Note: import is also a keyword (with all the
consequences of this fact).
Juniper
Business
Use Only
Let's assume that you want to use two entities provided by the math module:
a symbol (constant) representing a precise (as precise as possible using double floating-point
arithmetic) value of π (although using a Greek letter to name a variable is fully possible in Python,
the symbol is named pi - it's a more convenient solution, especially for that part of the world
which neither has nor is going to use a Greek keyboard)
a function named sin() (the computer equivalent of the mathematical sine function)
Both these entities are available through the math module, but the way in which you can use them
strongly depends on how the import has been done.
The simplest way to import a particular module is to use the import instruction as follows:
import math
Juniper
Business
Use Only
The instruction may be located anywhere in your code, but it must be placed before the first use of any of
the module's entities.
If you want to (or have to) import more than one module, you can do it by repeating the import clause
(preferred):
import math
import sys
The instruction imports two modules, first the one named math and then the second named sys .
A namespace is a space (understood in a non-physical context) in which some names exist and the names
don't conflict with each other (i.e., there are not two different objects of the same name). We can say that
each social group is a namespace - the group tends to name each of its members in a unique way (e.g.,
parents won't give their children the same first names).
Juniper
Business
Use Only
This uniqueness may be achieved in many ways, e.g., by using nicknames along with the first names (it
will work inside a small group like a class in a school) or by assigning special identifiers to all members of
the group (the US Social Security Number is a good example of such practice).
Inside a certain namespace, each name must remain unique. This may mean that some names may
disappear when any other entity of an already known name enters the namespace. We'll show you how it
works and how to control it, but first, let's return to imports.
If the module of a specified name exists and is accessible (a module is in fact a Python source file),
Python imports its contents, i.e., all the names defined in the module become known, but they don't
enter your code's namespace.
This means that you can have your own entities named sin or pi and they won't be affected by the
import in any way.
At this point, you may be wondering how to access the pi coming from the math module.
Juniper
Business
Use Only
To do this, you have to qualify the pi with the name of its original module.
math .pi
math .sin
Such a form clearly indicates the namespace in which the name exists.
This first example won't be very advanced - we just want to print the value of sin(½π).
Note: removing any of the two qualifications will make the code erroneous. There is no
other way to enter math 's namespace if you did the following:
import math
import math
print(math.sin(math.pi/2))
1.0
Juniper
Business
Use Only
Importing a module: continued
Now we're going to show you how the two namespaces (yours and the module's one) can
coexist.
Run the program. The code should produce the following output:
0.99999999
1.0
output
import math
def sin(x):
if 2 * x == pi:
return 0.99999999
else:
return None
pi = 3.14
print(sin(pi/2))
print(math.sin(math.pi/2))
0.99999999
1.0
print(sin(pi/2))
print(math.sin(pi/2))
0.99999999
0.9999996829318346
Juniper
Business
Use Only
from math import pi
the listed entities (and only those ones) are imported from the indicated module;
the names of the imported entities are accessible without qualification.
Note: no other entities are imported. Moreover, you cannot import additional entities using
a qualification - a line like this one:
print (math.e)
Here it is:
print (sin(pi/2))
The output should be the same as previously, as in fact we've used the same entities as
before: 1.0 . Copy the code, paste it in the editor, and run the program.
Does the code look simpler? Maybe, but the look is not the only effect of this kind of import.
Let's show you that.
print(sin(pi/2))
Juniper
Business
Use Only
def sin(x):
if 2 * x == pi:
return 0.99999999
else:
return None
pi = 3.14
print(sin(pi/2))
print(math.sin(math.pi/2))
1.0
0.99999999
1.0
print(sin(pi / 2))
pi = 3.14
def sin(x):
if 2 * x == pi:
return 0.99999999
else:
return None
print(sin(pi / 2))
1.0
0.99999999
Juniper
Business
Use Only
Let's do another test. Look at the code below:
pi = 3.14
def sin(x):
if 2 * x == pi:
return 0.99999999
else:
return None
Importing a module: *
In the third method, the import 's syntax is a more aggressive form of the previously
presented one:
As you can see, the name of an entity (or the list of entities' names) is replaced with a single
asterisk ( * ).
Is it convenient? Yes, it is, as it relieves you of the duty of enumerating all the names you
need.
Juniper
Business
Use Only
Is it unsafe? Yes, it is - unless you know all the names provided by the module, you may not
be able to avoid name conflicts. Treat this as a temporary solution, and try not to use it in
regular code.
Aliasing causes the module to be identified under a different name than the original. This
may shorten the qualified names, too.
Creating an alias is done together with importing the module, and demands the following
form of the import instruction:
The "module" identifies the original module's name while the "alias" is the name you wish to
use instead of the original.
import math as m
print (m.sin(m.pi/2))
Note: after successful execution of an aliased import, the original module name becomes
inaccessible and must not be used.
Juniper
Business
Use Only
In turn, when you use the from module import name variant and you need to change the
entity's name, you make an alias for the entity. This will cause the name to be replaced by
the alias you choose.
The phrase name as alias can be repeated - use commas to separate the multiplied
phrases, like this:
print (sine(PI/2))
Now you're familiar with the basics of using modules. Let us show you some modules and
some of their useful entities.
pi = 3.14
def sin(x):
if 2 * x == pi:
return 0.99999999
else:
return None
Juniper
Business
Use Only
Key takeaways
1. If you want to import a module as a whole, you can do it using the import module_name statement.
You are allowed to import more than one module at once using a comma-separated list. For example:
import mod1
import mod2, mod3, mod4
although the latter form is not recommended due to stylistic reasons, and it's better and prettier to express
the same intention in more a verbose and explicit form, such as:
import mod2
import mod3
import mod4
2. If a module is imported in the above manner and you want to access any of its entities, you need to
prefix the entity's name using dot notation. For example:
import my_module
result = my_module.my_function(my_module.my_data)
The snippet makes use of two entities coming from the my_module module: a function
named my_function() and a variable named my_data . Both names must be prefixed
by my_module. None of the imported entity names conflicts with the identical names existing in your
code's namespace.
3. You are allowed not only to import a module as a whole, but to import only individual entities from it.
In this case, the imported entities must not be prefixed when used. For example:
result = my_function(my_data)
Juniper
Business
Use Only
The above way - despite its attractiveness - is not recommended because of the danger of causing conflicts
with names derived from importing the code's namespace.
4. The most general form of the above statement allows you to import all entities offered by a module:
result = my_function(my_data)
Note: this import's variant is not recommended due to the same reasons as previously (the threat of a
naming conflict is even more dangerous here).
5. You can change the name of the imported entity "on the fly" by using the as phrase of the import . For
example:
result = fun(dat)
Exercise 1
You want to invoke the function make_money() contained in the module named mint . Your code
begins with the following line:
import mint
Check
mint.make_money()
Exercise 2
Juniper
Business
Use Only
You want to invoke the function make_money() contained in the module named mint . Your code
begins with the following line:
Check
make_money()
Exercise 3
You've written a function named make_money on your own. You need to import a function of the same
name from the mint module and don't want to rename any of your previously defined names. Which
variant of the import statement may help you with the issue?
Check
# sample solution
Exercise 4
What form of the make_money function invocation is valid if your code starts with the following line?
Check
make_money()
Juniper
Business
Use Only
Working with standard modules
Before we start going through some standard Python modules, we want to introduce the dir() function to
you. It has nothing to do with the dir command you know from Windows and Unix consoles,
as dir() doesn't show the contents of a disk directory/folder, but there is no denying that it does
something really similar - it is able to reveal all the names provided through a particular module.
There is one condition: the module has to have been previously imported as a whole (i.e., using
the import module instruction - from module is not enough).
The function returns an alphabetically sorted list containing all entities' names available in the module
identified by a name passed to the function as an argument:
dir (module)
Note: if the module's name has been aliased, you must use the alias, not the original name.
Using the function inside a regular script doesn't make much sense, but it is still possible.
For example, you can run the following code to print the names of all entities within the math module:
import math
output
Have you noticed these strange names beginning with __ at the top of the list? We'll tell you more about
them when we talk about the issues related to writing your own modules.
Juniper
Business
Use Only
Some of the names might bring back memories from math lessons, and you probably won't have any
problems guessing their meanings.
Using the dir() function inside a code may not seem very useful - usually you want to know a particular
module's contents before you write and run the code.
Fortunately, you can execute the function directly in the Python console (IDLE), without needing to write
and run a separate script.
import math
dir (math)
We've chosen them arbitrarily, but that doesn't mean that the functions we haven't
mentioned here are any less significant. Dive into the modules' depths yourself - we don't
have the space or the time to talk about everything in detail here.
The first group of the math 's functions are connected with trigonometry:
Juniper
Business
Use Only
sin(x) → the sine of x;
cos(x) → the cosine of x;
tan(x) → the tangent of x.
All these functions take one argument (an angle measurement expressed in radians) and
return the appropriate result (be careful with tan() - not all arguments are accepted).
These functions take one argument (mind the domains) and return a measure of an angle in
radians.
To effectively operate on angle measurements, the math module provides you with the
following entities:
Now look at the code in the editor. The example program isn't very sophisticated, but can
you predict its results?
Apart from the circular functions (listed above) the math module also contains a set of
their hyperbolic analogues:
from math import pi, radians, degrees, sin, cos, tan, asin
ad = 90
ar = radians(ad)
ad = degrees(ar)
print(ad == 90.)
Juniper
Business
Use Only
print(ar == pi / 2.)
print(sin(ar) / cos(ar) == tan(ar))
print(asin(sin(ar)) == ar)
True
True
True
True
Look at the code in the editor. Can you predict its output?
print(pow(e, 1) == exp(log(e)))
print(pow(2, 2) == exp(2 * log(2)))
print(log(e, e) == exp(0))
False
True
True
Juniper
Business
Use Only
ceil(x) → the ceiling of x (the smallest integer greater than or equal to x)
floor(x) → the floor of x (the largest integer less than or equal to x)
trunc(x) → the value of x truncated to an integer (be careful - it's not an equivalent
either of ceil or floor)
factorial(x) → returns x! (x has to be an integral and not a negative)
hypot(x, y) → returns the length of the hypotenuse of a right-angle triangle with
the leg lengths equal to x and y (the same as sqrt(pow(x, 2) + pow(y, 2)) but
more precise)
x = 1.4
y = 2.6
print(floor(x), floor(y))
print(floor(-x), floor(-y))
print(ceil(x), ceil(y))
print(ceil(-x), ceil(-y))
print(trunc(x), trunc(y))
print(trunc(-x), trunc(-y))
1 2
-2 -3
2 3
-1 -2
1 2
-1 -2
Juniper
Business
Use Only
Note the prefix pseudo - the numbers generated by the modules may look random in the
sense that you cannot predict their subsequent values, but don't forget that they all are
calculated using very refined algorithms.
The algorithms aren't random - they are deterministic and predictable. Only those physical
processes which run completely out of our control (like the intensity of cosmic radiation)
may be used as a source of actual random data. Data produced by deterministic computers
cannot be random in any way.
A random number generator takes a value called a seed, treats it as an input value, calculates a "random"
number based on it (the method depends on a chosen algorithm) and produces a new seed value.
The length of a cycle in which all seed values are unique may be very long, but it isn't infinite - sooner or
later the seed values will start repeating, and the generating values will repeat, too. This is normal. It's a
feature, not a mistake, or a bug.
The initial seed value, set during the program start, determines the order in which the generated values will
appear.
The random factor of the process may be augmented by setting the seed with a number taken from the
current time - this may ensure that each program launch will start from a different seed value (ergo, it will
use different random numbers).
Juniper
Business
Use Only
The most general function named random() (not to be confused with the module's
name) produces a float number x coming from the range (0.0, 1.0) - in other words:
(0.0 <= x < 1.0).
The example program below will produce five pseudorandom values - as their values are
determined by the current (rather unpredictable) seed value, you can't guess them:
for i in range(5):
print(random())
0.9535768927411208
0.5312710096244534
0.8737691983477731
0.5896799172452125
0.02116716297022092
sample output
The seed function
The seed() function is able to directly set the generator's seed. We'll show you two of its
variants:
We've modified the previous program - in effect, we've removed any trace of randomness
from the code:
seed (0)
for i in range(5):
print(random())
Due to the fact that the seed is always set with the same value, the sequence of generated
values always looks the same.
0.844421851525
Juniper
Business
Use Only
0.75795440294
0.420571580831
0.258916750293
0.511274721369
sample output
And you?
Note: your values may be slightly different than ours if your system uses more precise or
less precise floating-point arithmetic, but the difference will be seen quite far from the
decimal point.
If you want integer random values, one of the following functions would fit better:
randrange(end)
randrange(beg, end)
randrange(beg, end, step)
randint(left, right)
The first three invocations will generate an integer taken (pseudorandomly) from the range
(respectively):
range(end)
range(beg, end)
range(beg, end, step)
The last function is an equivalent of randrange(left, right+1) - it generates the integer
value i , which falls in the range [left, right] (no exclusion on the right side).
Look at the code in the editor. This sample program will consequently output a line
consisting of three zeros and either a zero or one at the fourth place.
0 0 0 1
Juniper
Business
Use Only
Selected functions from the random module: continued
The previous functions have one important disadvantage - they may produce repeating
values even if the number of subsequent invocations is not greater than the width of the
specified range.
Look at the code below - the program very likely outputs a set of numbers in which some
elements are not unique:
for i in range(10):
print(randint(1, 10), end=',')
9,4,5,4,5,8,9,4,8,4,
sample output
The choice and sample functions
As you can see, this is not a good tool for generating numbers in a lottery. Fortunately, there
is a better solution than writing your own code to check the uniqueness of the "drawn"
numbers.
choice(sequence)
sample(sequence, elements_to_choose)
The first variant chooses a "random" element from the input sequence and returns it.
The second one builds a list (a sample) consisting of the elements_to_choose element
"drawn" from the input sequence.
In other words, the function chooses some of the input elements, returning a list with the
choice. The elements in the sample are placed in random order. Note:
the elements_to_choose must not be greater than the length of the input sequence.
Juniper
Business
Use Only
print (choice(my_list))
print (sample(my_list, 5))
print (sample(my_list, 10))
Again, the output of the program is not predictable. Our results looked like this:
4
[3, 1, 8, 9, 10]
[10, 8, 5, 1, 6, 4, 3, 9, 7, 2]
output
Juniper
Business
Use Only
the next layer of the pyramid is filled with the OS (operating system) - Python's environment
provides some of its functionalities using the operating system's services; Python, although very
powerful, isn't omnipotent - it's forced to use many helpers if it's going to process files or
communicate with physical devices;
the bottom-most layer is hardware - the processor (or processors), network interfaces, human
interface devices (mice, keyboards, etc.) and all other machinery needed to make the computer
run; the OS knows how to drive it, and uses lots of tricks to conduct all parts in a consistent
rhythm.
This means than some of your (or rather your program's) actions have to travel a long way to be
successfully performed - imagine that:
Usually, you're not aware of all that fuss - you want the file to be created and that's that.
But sometimes you want to know more - for example, the name of the OS which hosts Python, and some
characteristics describing the hardware that hosts the OS.
There is a module providing some means to allow you to know where you are and what components work
for you. The module is named platform. We'll show you some of the functions it provides to you.
The platform module lets you access the underlying platform's data, i.e., hardware,
operating system, and interpreter version information.
There is a function that can show you all the underlying layers in one glance,
named platform , too. It just returns a string describing the environment; thus, its output is
rather addressed to humans than to automated processing (you'll see it soon).
Juniper
Business
Use Only
And now:
aliased → when set to True (or any non-zero value) it may cause the function to
present the alternative underlying layer names instead of the common ones;
terse → when set to True (or any non-zero value) it may convince the function to
present a briefer form of the result (if possible)
We ran our sample program using three different platforms - this is what we got:
Windows-Vista-6.0.6002-SP2
Windows-Vista-6.0.6002-SP2
Windows-Vista
output
Linux-3.18.62-g6-x86_64-Intel-R-_Core-TM-_i3-2330M_CPU_@_2.20GHz-with-
gentoo-2.3
Linux-3.18.62-g6-x86_64-Intel-R-_Core-TM-_i3-2330M_CPU_@_2.20GHz-with-
gentoo-2.3
Linux-3.18.62-g6-x86_64-Intel-R-_Core-TM-_i3-2330M_CPU_@_2.20GHz-with-
glibc2.3.4
output
Linux-4.4.0-1-rpi2-armv7l-with-debian-9.0
Linux-4.4.0-1-rpi2-armv7l-with-debian-9.0
Linux-4.4.0-1-rpi2-armv7l-with-glibc2.9
output
You can also run the sample program in IDLE on your local machine to check what output
you will have.
print(platform())
print(platform(1))
print(platform(0, 1))
Linux-4.4.0-206-generic-x86_64-with
Linux-4.4.0-206-generic-x86_64-with
Linux-4.4.0-206-generic-x86_64-with
Juniper
Business
Use Only
Selected functions from the platform module:
continued
The machine function
Sometimes, you may just want to know the generic name of the processor which runs your
OS together with Python and your code - a function named machine() will tell you that. As
previously, the function returns a string.
x86
output
x86_64
output
armv7l
print(machine())
x86_64
The processor() function returns a string filled with the real processor name (if possible).
x86
Juniper
Business
Use Only
output
output
armv7l
output
print(processor())
Windows
output
Linux
output
Linux
Juniper
Business
Use Only
Selected functions from the platform module:
continued
The version function
Run the code and check its output. This is what we got:
6.0.6002
output
output
output
If you need to know what version of Python is running your code, you can check it using a
number of dedicated functions - here are two of them:
Juniper
Business
Use Only
Our example program produced the following output:
CPython
3
7
7
sample output
Moreover, the Python community all over the world creates and maintains hundreds of additional modules
used in very niche applications like genetics, psychology, or even astrology.
These modules aren't (and won't be) distributed along with Python, or through official channels, which
makes the Python universe broader - almost infinite.
Don't worry - you won't need all these modules. Many of them are very specific.
All you need to do is find the modules you want, and teach yourself how to use them. It's easy.
Juniper
Business
Use Only
In the next section we'll take a look at something else. We're going to show you how to write your own
module.
Key takeaways
1. A function named dir() can show you a list of the entities contained inside an imported module. For
example:
import os
dir (os)
Juniper
Business
Use Only
prints out the list of all the os module's facilities you can use in your code.
2. The math module couples more than 50 symbols (functions and constants) that perform mathematical
operations (like sine() , pow() , factorial() ) or providing important values (like π and the Euler
symbol e).
3. The random module groups more than 60 entities designed to help you use pseudo-random numbers.
Don't forget the prefix "random", as there is no such thing as a real random number when it comes to
generating them using the computer's algorithms.
4. The platform module contains about 70 functions which let you dive into the underlaying layers of
the OS and hardware. Using them allows you to get to know more about the environment in which your
code is executed.
Exercise 1
What is the expected value of the result variable after the following code is executed?
import math
result = math.e == math.exp(1)
Check
True
Juniper
Business
Use Only
Exercise 2
(Complete the sentence) Setting the generator's seed with the same value each time your program is run
guarantees that...
Check
... the pseudo-random values emitted from the random module will be exactly the same.
Exercise 3
Which of the platform module's functions will you use to determine the name of the CPU running
inside your computer?
Check
Exercise 4
import platform
print(len(platform.python_version_tuple()))
Check
What is a package?
Writing your own modules doesn't differ much from writing ordinary scripts.
There are some specific aspects you must be aware of, but it definitely isn't rocket science. You'll see this
soon enough.
Juniper
Business
Use Only
Let's summarize some important issues:
a module is a kind of container filled with functions - you can pack as many functions as you
want into one module and distribute it across the world;
of course, it's generally a good idea not to mix functions with different application areas within
one module (just like in a library - nobody expects scientific works to be put among comic books),
so group your functions carefully and name the module containing them in a clear and intuitive
way (e.g., don't give the name arcade_games to a module containing functions intended to
partition and format hard disks)
making many modules may cause a little mess - sooner or later you'll want to group your
modules exactly in the same way as you've previously grouped functions - is there a more general
container than a module?
yes, there is - it's a package; in the world of modules, a package plays a similar role to a
folder/directory in the world of files.
Juniper
Business
Use Only
module.py
You will need two files to repeat these experiments. The first of them will be the module itself. It's empty
now. Don't worry, you're going to fill it with actual code soon.
We've named the file module.py. Not very creative, but simple and clear.
import module
main.py
Juniper
Business
Use Only
Note: both files have to be located in the same folder. We strongly encourage you to create an empty,
new folder for both files. Some things will be easier then.
Launch IDLE (or any other IDE you prefer) and run the main.py file. What do you see?
You should see nothing. This means that Python has successfully imported the contents of
the module.py file.
It doesn't matter that the module is empty for now. The very first step has been done, but before you take
the next step, we want you to take a look into the folder in which both files exist.
A new subfolder has appeared - can you see it? Its name is __pycache__. Take a look inside. What do
you see?
The name of the file is the same as your module's name (module here). The part after the first dot says
which Python implementation has created the file (CPython here) and its version number. The last part
(pyc) comes from the words Python and compiled.
You can look inside the file - the content is completely unreadable to humans. It has to be like that, as the
file is intended for Python's use only.
When Python imports a module for the first time, it translates its contents into a somewhat compiled
shape.
The file doesn't contain machine code - it's internal Python semi-compiled code, ready to be executed by
Python's interpreter. As such a file doesn't require lots of the checks needed for a pure source file, the
execution starts faster, and runs faster, too.
Thanks to that, every subsequent import will go quicker than interpreting the source text from scratch.
Python is able to check if the module's source file has been modified (in this case, the pyc file will be
rebuilt) or not (when the pyc file may be run at once). As this process is fully automatic and transparent,
you don't have to keep it in mind.
Juniper
Business
Use Only