Programming in Python - the basics

Syntax in Python

Variables

Some general considerations

  • In Python, a variable is created when you first assign a value to it
planet = 'Jupiter'
  • The name of a variable cannot start with a digit or contain a special symbol (e.g., |£$%@#)
  • Some keywords cannot be used for naming variables.
False | class | finally | is | return | None | continue | for | lambda | try | True | def
from | nonlocal | while | and | del | global | not | with | as | elif | if | or
yield | assert | else | import | pass | break | except | in | raise
  • Python is case-sensitive: planet and Planet are different variables

Naming conventions

The following naming styles are commonly distinguished:

  • snake case: lower_case_with_underscores
  • CamelCase: CapitalizedWords
  • mixedCase: differs from CamelCase by initial lowercase character

Python naming convention

The Python Enhancement Proposal number 8 (PEP 8) states:

Function names should be lowercase, with words separated by underscores as necessary to improve readability. Variable names follow the same convention as function names.

Use names that make sense: planet = 'Jupiter' rather than p = 'Jupiter'

Punctuation and indentation

You don't need to add punctuation at the end of lines

planet = 'Jupiter'
position_from_sun = 5

Use semicolons in case you want to put multiple statements in a single line

planet = 'Jupiter' ; position_from_sun = 5

Document your code using comments

# this is the first comment
planet = 'Jupiter'  # and this is the second comment
          # ... and now a third!
text = "# This is not a comment because it's inside quotes."

Data types

Numbers

# Integers
known_satellites = 80

# Floating point numbers
hydrogen_percentage = 0.89

The int() and float() methods convert booleans, numbers and number-like strings to integers and floating point numbers

known_satellites = int('80')
# 80
the_world_is_flat = float(True)
# 1.0
the_world_is_flat = float(False)
# 0.0

Strings

planet = 'Jupiter' # This is a string

The str() method returns the string representation of a given object

known_satellites = str(80)
# Use the type() function to return the type of the object
print(type(known_satellites))
# <class 'str'>

Lists

# You can initialise an empty list with the list() method
planets = list()
# Or using square brackets
planets = []
# To fill the list, you can put the items separated by commas between square brackets
planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus']

# In Python you count from zero
print(planets[4]) # Jupiter

# To sort the list
planets_sorted_alphabetically = sorted(planets)
# planets = ['Earth', 'Jupiter', 'Mars', 'Mercury', 'Saturn', 'Uranus', 'Venus']

# Add a new item to the list
planets.append('Neptune')
# planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']

# Count how many elements we have in a list
planets_count = len(planets) # 8

String interpolation

String interpolation is the process of substituting values of variables into placeholders in a string

print("The fifth planet is %s" %(planets[4]))

print("The fifth planet is {}".format(planets[4]))

print(f"The fifth planet is {planets[4]}")

# The fifth planet is Jupiter

Operators

Arithmetic operators

x = 5
y = 2

# + Add two operands
print(x + y) # 7

# - Subtract the right operand from the left one
print(x - y) # 3

# * Multiply two operands
print(x * y) # 10

# / Divide the left operand by the right one. Division always returns a floating point number
print(x / y) # 2.5

# ** Raise the left operand to the power of the right one
print(x ** y) # 25

# % Return the remainder of the division. It is called modulus
print(x % y) # 1

# // Discard the fractional part of the division's result. It is called floor division
print(x // y) # 2

Comparison operators

x = 5
y = 2

# > Greater than - True if the left operand is greater than the right one
print(x > y) # True

# < Less than - True if the left operand is less than the right one
print(x < y) # False

# == Equal to - True if both operands are equal
print(x == y) # False

# != Not equal to - True if operands are not equal
print(x != y) # True

# >= Greater than or equal to - True if the left operand is greater than or equal to the right one
print(x >= y) # True

# <= Less than or equal to - True if the left operand is less than or equal to the right one
print(x <= y) # False
Note the difference: = is an assignment operator, used to assign a value to a variable. Conversely, == is a Boolean operator that checks whether the right operand is equal to the left one

Logic operators

x = True
y = False

# "and": True if both the operands are true
print(x and y) # False

# "or": True if at least one of the operands is true
print(x or y) # True

# "not": True if the operand is False and viceversa
print(not x) # False

Assignment operators

# with "="
x = 5
print(x)

# with "+="
x += 5 # A shortcut for x = x + 5
print(x)

# with "-="
x -= 2 # A shortcut for x = x - 2
print(x)

# Try with other arithmetic operands ...

Membership operators

planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus']

# "in": True if value/variable is found in the sequence
print('Pluto' in planets) # False

# "not in": True if value/variable is not found in the sequence
print('Moon' not in planets) # True

Conditional statement

A decision might be taken only when a specific condition is satisfied

the_world_is_flat = True
if the_world_is_flat:
  print("Be careful not to fall off!")

Use indentation to separate code blocks by pressing the key.

A block is a piece of Python program text that is executed as a unit, i.e., a conditional statement or a function body

Functions

A block of code which defines a specific algorithm and runs only when it is called

# def {func_name}({parameter_1}, {parameter_2}, ...):
  # {func_body}
def add(num1, num2):
    return num1 + num2

my_sum = add(5,4)
print(my_sum) # 9

Exercises

1st Exercise

The function is_friend_of_harry() returns a True value if a given name (i.e. type string) is one of the friends of Harry Potter, otherwise the function returns False. Let's pretend the friends of Harry Potter are: "Ron", "Hermione", "Hagrid", and "Dumbledore".

Example: calling the function is_friend_of_harry("Malfoy") returns False.

1.a) Define the function is_friend_of_harry(), and call it for each one of the following characters: "Hagrid", "Voldemort", and "Bellatrix". Print the result (i.e. True/False) of each call.

def is_friend_of_harry(name):
  friends_list = ["Ron", "Hermione", "Hagrid", "Dumbledore"]
  if name in friends_list:
    return True
  else:
    return False
print(is_friend_of_harry("Hagrid"))
print(is_friend_of_harry("Voldemort"))
print(is_friend_of_harry("Bellatrix"))

1.b) Write a portion of code that prints "Harry has friends!" if at least one of the previous characters is a friend of Harry, otherwise, print "Harry has no friends!".

is_hagrid_friend = is_friend_of_harry("Hagrid")
is_voldemort_friend = is_friend_of_harry("Voldemort")
is_bellatrix_friend = is_friend_of_harry("Bellatrix")
if is_hagrid_friend or is_voldemort_friend or is_bellatrix_friend:
    print("Harry has friends!")
else:
    print("Harry has no friends!!")

1.c) Let's make our function is_friend_of_harry() a bit more powerful. The new function should work the same way even if the given name is not well written, such that it should handle these cases:

  • a) The letters of the name are written in different formats: uppercase and lowercase (e.g. "ron", "RON", "Ron", "roN")
  • b) The name includes spaces (e.g. "Ron ", " Ron")
  • c) The name has both (a) and (b) cases combined in it (e.g. " roN")

Hint: in python {string}.lower() transforms a string to its lowercase form; {string}.strip() removes the starting and ending whitespaces (if any); and {string}.capitalize() capitalizes the first letter of a string

def is_friend_of_harry(name):
  friends_list = ["Ron", "Hermione", "Hagrid", "Dumbledore"]
  name = name.lower()
  name = name.strip()
  name = name.capitalize()
  if name in friends_list:
    return True
  else:
    return False

1.d) Define another function is_prof_friend_of_harry() which returns a True value if a given name, which might be written in any format described (1.c), is a professor and a friend of Harry, otherwise the function must return False. The function should call the improved version of the function is_friend_of_harry() in its code (i.e. defined in (1.c)). Let's pretend the professors of Harry Potter are: "Snape", "Umbridge", and "Hagrid".

def is_prof_friend_of_harry(name):
  prof_list = ["Snape", "Umbridge", "Hagrid"]
  name = name.lower()
  name = name.strip()
  name = name.capitalize()
  if name in prof_list and is_friend_of_harry(name):
    return True
  else:
    return False
print(is_prof_friend_of_harry("snape"))
print(is_prof_friend_of_harry(" umbridge  "))
print(is_prof_friend_of_harry("  hagrid"))

2nd Exercise

Each house of Hogwarts has a score which is updated with the addition or subtraction of points based on the behaviour of the houses' members, e.g. after a rule violation. We have two lists:

  • the houses of Hogwarts houses = ["Gryffindor", "Hufflepuff", "Ravenclaw", "Slytherin"]
  • the score of each house scores = [0,0,0,0]. The score of a house in position n in houses is placed in the same position n in scores.

2.a) Define the function update_house_score() which increments/decrements the score of a specific house with a given value of points. The function takes three parameters: house_name, action, and points. The value of action is a string which is either "+"(points will be added) or "-" (points will be subtracted)
Example: Calling the function this way: update_house_score("Gryffindor", "+", 5) should increment the score of house Gryffindor by 5 points.
Hint: The function {list}.index({value}) returns the index of an element in the list, e.g. houses.index("Hufflepuff") returns the value 1

houses = ["Gryffindor", "Hufflepuff", "Ravenclaw", "Slytherin"]
scores = [0,0,0,0]
def update_house_score(house_name, action, points):
  house_index = houses.index(house_name)
  if action == "+":
    scores[house_index] += points
  else:
    scores[house_index] -= points

2.b) After the Quidditch cup the Houses have increased/decreased their scores: +10 Gryffindor, +7 Hufflepuff, -3 Slytherin. After the end of the game a member of house "Slytherin" helped a man riding his broom, so his house gained back 5 points. Call the function update_house_score() for each action in order to update the houses points and print the two lists: houses and scores.

update_house_score("Gryffindor", "+", 10)
update_house_score("Hufflepuff", "+", 7)
update_house_score("Slytherin", "-", 3)
update_house_score("Slytherin", "+", 5)
print(houses)
print(scores)

2.c) redefine update_house_score() using the function eval() (https://docs.python.org/3/library/functions.html#eval)

def update_house_score(house_name, action, points):
    house_index = houses.index(house_name)
    scores[house_index] = eval(str(points) + action + str(scores[house_index]))
    return scores