Let's start with strings

We assume you know how to program. You don't need to learn what a loop or a variable is!

We are starting with strings as this is a type common to most languages so you likely know what it is. But they also allow us to introduce lots of Python concepts!

Using strings, we'll have a look at the following:

  • what object-oriented language means
  • the print() function and how to format a string
  • indexing
  • loops
  • if constructs
In [1]:
# First variable
a = "Claire"
In [2]:
a  # Easy to get the value of a variable in a notebook
Out[2]:
'Claire'
In [3]:
# Can be done in one cell:
a = "Claire"
a
Out[3]:
'Claire'
In [4]:
# Python is case sensitive
A
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-4-62579e0dbc5d> in <module>
      1 # Python is case sensitive
----> 2 A

NameError: name 'A' is not defined
In [5]:
# You can add strings:
b = " Carouge"
c = a+b
c
Out[5]:
'Claire Carouge'

Object-oriented language

Everything is an object in Python. That means a variable contains more than a value. It may also contain:

  • functions, called methods. These are specific to each object type. A string and an array won't have the same methods.
  • attributes. These are additional information about the object. Think of it a bit like meta-data. Attributes differ from methods because they simply contain a value and not a function.
In [38]:
# Find out the type of an object
?a
a.split()
In [7]:
type(a)
Out[7]:
str
In [8]:
# Find all attributes/methods of an object
dir(a)
Out[8]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mod__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rmod__',
 '__rmul__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'capitalize',
 'casefold',
 'center',
 'count',
 'encode',
 'endswith',
 'expandtabs',
 'find',
 'format',
 'format_map',
 'index',
 'isalnum',
 'isalpha',
 'isascii',
 'isdecimal',
 'isdigit',
 'isidentifier',
 'islower',
 'isnumeric',
 'isprintable',
 'isspace',
 'istitle',
 'isupper',
 'join',
 'ljust',
 'lower',
 'lstrip',
 'maketrans',
 'partition',
 'replace',
 'rfind',
 'rindex',
 'rjust',
 'rpartition',
 'rsplit',
 'rstrip',
 'split',
 'splitlines',
 'startswith',
 'strip',
 'swapcase',
 'title',
 'translate',
 'upper',
 'zfill']

It doesn't tell you if those are methods or simple attributes. There is no information on what the method does. Inline help can help here.


Obviously, there is a print() function builtin. It can print out the values in all sorts of objects, not just strings.

In [9]:
print(a)
Claire
In [10]:
# Print several variables together:
print("My var is:",a)
My var is: Claire
In [11]:
b = "it's me"
print(a,",",b)
Claire , it's me

Formatting

It is possible to format a string in Python and there are several ways to do that.

Let's start with the new way: f-string

In [12]:
a = 100.
b = 50
print(f"It's {b}% off, it costs {a} dollars")  # You put the name of the variable directly in the string
It's 50% off, it costs 100.0 dollars

It is possible to describe the format of the variable in the string.

There are lots of possibilities to format strings. Python refer to it as "Format Specification Mini-Language". The complete documentation is here: https://docs.python.org/3/library/string.html#formatspec

A few examples below:

In [13]:
# Format a fixed-point number
print(f"It's {b}% off, it costs {a:3.0f} dollars") # Same formatting options
It's 50% off, it costs 100 dollars

Above we said we wanted a fixed-point notation, with an overall width of 3 charaters and 0 characters after the decimal point (called the precision).

In [14]:
# Pad a number on the left with zeros. Remember the type of your variable!
b=f"{a:0>6}"
c=f"{a:0>6.0f}"
print(b)
print(c)
0100.0
000100
In [15]:
# Exponent notation:
print(f"{a:e}")
print(f"{a:.3e}")
1.000000e+02
1.000e+02

Another method of formating is the string method: str.format()

In [16]:
print("It's {} dollars".format(a))
It's 100.0 dollars

When putting several variables into the same string, it allows you to refer to the str.format() arguments by position or name:

In [17]:
a=100.
b=50
print("It's {1}% off, it costs {0} dollars".format(a,b))
print("It's {perc}% off, it costs {cost} dollars".format(perc=b, cost=a))
It's 50% off, it costs 100.0 dollars
It's 50% off, it costs 100.0 dollars
In [18]:
# Add some formatting
print("It's {cost:3.0f} dollars".format(cost=a))  # with keyword argument
print("It's {:3.0f} dollars".format(a))  # with just an argument
It's 100 dollars
It's 100 dollars

If you want to learn more but find the Python manual a bit heavy in details:

https://realpython.com/python-f-strings/#python-f-strings-the-pesky-details

Finally there is an old way you shouldn't use. We only see it because you might encounter it:

In [19]:
print("It's %s dollars"%a)
It's 100.0 dollars

Indexing

Strings are indexable in Python. Indexes start at 0 in Python. It's possible to have negative indexes, thus -1 refers to the last element.

In [20]:
a = 'Claire'
a[1]
Out[20]:
'l'
In [21]:
a[-1]
Out[21]:
'e'
In [22]:
a[-3]
Out[22]:
'i'

len() function

This is a builtin function in Python. It returns the length of a whole bunch of objects. Be careful when using it with more complex objects as it might not return what you'd like as we'll see later

In [23]:
len(a)
Out[23]:
6

Slicing

In [24]:
print(a[0:1]) # Last index isn't included. Same as a[0]
print(a[0:3])
print(a[:3]) # Start and end indexes can be omitted. This means everything from start to index 3-1
print(a[3:]) # Means everything from index 3 to the end.
print(a[::2]) # You can use a stride. It means from start to end, print every other character.
print(a[0:-1]) # That's not the whole string!
print(a[:-1]) # This neither
print(a[0:len(a)]) # The whole string
print(a[0:len(a)-3]) # You can obviously have expressions to define the indexes
C
Cla
Cla
ire
Car
Clair
Clair
Claire
Cla

The slice 0:3 means, “Start at index 0 and go up to, but not including, index 3.” The up-to-but-not-including takes a bit of getting used to, but the rule is that the difference between the upper and lower bounds is the number of values in the slice.

But it's nice as it avoids having a -1 all the time. For example, to get the 3 first character, you use this slice :3. If the last index was including, you would need: :3-1. If you want 2 characters from the 2nd character, you do 2:2+2 and not 2:2+2-1. Etc.


Loops

Important note: Loops are very ineficient in Python. It is best to avoid them as much as possible. It isn't always possible obviously but it is something you should keep in mind.

You can loop on any iterable! No just a range of numbers.

In [25]:
for char in a:
    print(char)
C
l
a
i
r
e

Note the syntax! for, in, :, indentation to define what is in the loop.

In [26]:
for char in a:
    print("Indentation = in the loop")
    print("Still in")
print("This is outside the loop because it is not indented")
Indentation = in the loop
Still in
Indentation = in the loop
Still in
Indentation = in the loop
Still in
Indentation = in the loop
Still in
Indentation = in the loop
Still in
Indentation = in the loop
Still in
This is outside the loop because it is not indented
In [27]:
# Different indentations = error
for char in a:
    print("Hey")
        print("OK?")
  File "<ipython-input-27-e33d7e7bd96a>", line 4
    print("OK?")
    ^
IndentationError: unexpected indent

Loop over a range:

In [28]:
for i in range(3,17,2):   # End index is excluded here again! There is some consistency.
    print(i)
3
5
7
9
11
13
15
In [29]:
for i in range(5):
    print(i)
0
1
2
3
4

Nested loop

In [30]:
for i in range(2):
    for char in a[:3]:
        print(char)
    print("Index:",i)  # In outer loop but not inner loop
C
l
a
Index: 0
C
l
a
Index: 1

Break / continue statements

In [31]:
for i in range(10):
    if i == len(a):
        break
i
Out[31]:
6

There is also a while construct, which you can discover on your own. It has a similar syntax as the for loop construct.


If constructs

In [32]:
if "l" in a:
    print("Yeah")
Yeah
In [33]:
if "Claire" == a:
    print("Yeah")
Yeah
In [34]:
# Negation
if "Claire" != a:
    print("yeah")
if not "z" in a:
    print("oh!")
if "z" not in a:
    print("oh!")
oh!
oh!
In [35]:
# and / or
if not "z" in a and "l" in a:
    print("yeah")
yeah

any() and all() functions

Python has any() and all() functions as built-in.

any(x) returns true if at least 1 value in x is True,

all(x) returns true if all values in x are True or x is null.

In Python, 0, False and None are False. Everything else is True

In [36]:
all(a)
Out[36]:
True
In [37]:
b=""
print(all(b), any(b))
True False