Instruction
Python Basics
Now that you’ve set up your environment and know how to run commands, it’s time to learn the basics of the Python programming language.
Data Types and Variables
To create a new variable in Python, simply use the assignment operator, =
, to assign a value to a new variable name. Python does not require you to specify the variable’s type. Instead, it infers the variable’s type from the value assigned to it.
Here are some examples:
score = 200 # int
time_travel_gigawatts = 1.21 # float
greeting = "Welcome to Python" # string
is_user_logged_in = True # boolean
Note: In Python, boolean values are capitalized:
True
andFalse
, nottrue
andfalse
.
Python doesn’t have constants, just variables.
Data Types
Python has the following basic data types:
-
int
: Integers -
float
: Floating-point numbers -
complex
: Complex numbers -
str
: Strings -
bool
: Booleans
Python’s type()
function takes an object and returns that object’s type.
Converting Values to Other Types
Everything in Python is an object, even basic data types. This means you can create any variable using object initialization syntax.
score = int(200)
message = str("Hi there!")
But it’s also useful for converting values of one type to another. You can use any of these initializer methods to do type conversion:
The None
Value
Python has a special value called None
, which represents a null value or the absence of a value, like nil
or null
in other programming languages. None is the only member of its own type, NoneType
.
One common use of None
is initializing variables that will be assigned a value later.
Variable Naming Conventions
The Python community has adopted several stylistic conventions, one of which is snake case for variable names: all lowercase letters, with words separated by underscores:
# Example variable names
score
high_score
all_time_high_score
To make up for a lack of constants, many Python programmers follow the convention of naming them using only uppercase letters with underscore characters separating words for legibility:
# Example constant names
BASELINE
AVOGADRO_NUMBER
UNIVERSAL_GRAVITATIONAL_CONSTANT
Deleting Variables
Unlike most languages, Python has a statement that deletes objects from memory, which includes a variable: del
.
Here’s an example:
my_variable = "I won't be around for long."
del my_variable
my_variable # "NameError: name 'my_variable' is not defined"
Notice that del
is a statement, not a function. You don’t need to put parentheses around the variable to be deleted.
String Interpolation With f-Strings
The simplest and most readable way to perform string interpolation in Python is to use f-strings, which stands for formatted strings.
f-strings are delimited by quotes where the opening quote is preceded by f
. Any value, object, or expression that you want interpolated into the f-string should be contained in braces,{
and }
:
name = "Alice"
# Alice needs 714 floor tiles.
print(f"{name} needs {21 * 34} floor tiles.")
Multi-Line Strings
Python uses triple quotes, '''
or """
, to delimit string literals with multiple lines:
message = """Here is
an example
of a multi-line string
in Python."""
Multi-line strings can also be f-strings:
items_count = 3
price = 8.62
print(f"""Your cost
for {items_count} items at ${price} each
is {items_count * price}.""")
Getting User Input With input()
Python’s input()
function presents the user with an optional prompt, waits for them to enter something, and returns the user’s input as a string. In Jupyter, it presents the prompt beside a text box where the user can enter text:
# Putting a space at the end of an `input()` prompt
# provides a little distance between the prompt
# and the text input box.
name = input("What is your name? ")
print(f"That's funny, my dog's name is {name}.")
String Methods
You may find the following string methods useful:
Comparison and Boolean Logic Operators in Python
Python uses the standard comparison operators found in other programming languages, but its boolean logic operators may differ from the ones you usually use:
-
not
instead of!
-
and
instead of&&
-
or
instead of||
not
has higher precedence than and
, which has higher precedence than or
.
if
and Indentation
Python’s if
statement works almost as you might expect, but there are differences in syntax from other programming languages:
status = input("Is the job complete? ").strip().lower()
if status == "y" or status == "yes":
print("Hooray! The job is complete!")
print("Take a moment to celebrate.")
print("But afterward, get back to work!") # Last line of `if` block
print("Now on to the rest of the program.")
Note the following:
- The expression following
if
is not in parentheses. Python doesn’t require parentheses around anif
statement’s test expression. It’s part of the Python philosophy of readability and simplicity. - The
if
statement ends with the colon,:
, character, which means that a code block will start on the next line. - The end of the
if
block is indicated by the end of the indentation. In the example above, “Now on to the rest of the program.” will always be printed, regardless of the value ofstatus
.
else
The else
keyword works as you might expect. You start with if
statement and a condition, if that condition is true
a code block executes, otherwise the else
block gets executed:
status = input("Is the job complete? ").strip().lower()
if status == "y" or status == "yes":
print("Hooray! The job is complete!")
print("Take a moment to celebrate.")
print("But afterward, get back to work!")
else:
print("Well, keep working at it.")
print("We'll celebrate when it's done.") # Last line of `else` block
print("Now on to the rest of the program.")
elif
Python has the elif
keyword, which is a compressed, combined version of the else if
statement used in other programming languages:
status = input("Is the job complete? ").strip().lower()
if status == "y" or status == "yes":
print("Hooray! The job is complete!")
print("Take a moment to celebrate.")
print("But afterward, get back to work!")
elif status == "n" or status == "no":
print("Well, keep working at it.")
print("We'll celebrate when it's done.") # Last line of `elif` block
else:
print("You're not good at following instructions.")
print("This will go in your permanent record.")
print("Now on to the rest of the program.")
while
Loops
Python has only two kinds of loop statements, the first of which is the while
loop. It functions like the while
loops in most other programming languages:
count = 0
while count < 5:
print(f"The current count is {count}.")
count += 1
You don’t have to put the conditional expression — the count < 5
part — in parentheses, just as they’re not required in Python’s if
and elif
statements.
break
Like other programming languages, you can use the break
statement to exit a loop from within:
while True:
response = input("Continue? Enter \"y\" or \"n\". ")
if response == "y" or response == "n":
break
print(f"Your response was \"{response}\".")
continue
Python also provides the continue
statement, which sends the program back to the start of the loop, where it starts the next iteration:
count = 0
while count < 20:
count += 1
# True if `count` is evenly divisible by 3
if count % 3 == 0:
continue
print(f"The current number is {count},")
print("and it's not evenly divisible by 3.")
else
The ‘else’ keyword is an unusual and often overlooked feature of Python’s loops. It lets you define a block of code that will execute only when the loop completes “normally”, that is, without executing the break
statement while in the loop.
In this first example, the code prints out the numbers 0 through 4 followed by “Done!” because the break
statement is never executed:
count = 0
while count < 5:
print(count)
count += 1
else:
print("Done!")
This code prints out the numbers 0 through 3, but does not print “Done!”
count = 0
while count < 5:
print(count)
if count == 3:
break
count += 1
else:
print("Done!")
If the code in a loop never executes, it never encounters the break
statement and exits normally. This means that the else
block is executed:
while False:
print("This will never execute...")
else:
print("...but this will!")
Sequence Types: Strings, Lists, and Tuples
Python has three built-in sequence types, which are data types that hold multiple values in a specific order. They are:
-
Strings: Like strings in other programming languages and are delimited by quotes (
'
,"
, or"""
). Strings are immutable. -
Lists: Similar to arrays in other languages but more flexible, they are delimited by
[
and]
. Lists are mutable. -
Tuples: Like Python lists but immutable and are delimited by
(
and)
.
Here are examples of creating a non-empty string, list, and tuple using literal string, list, and tuple values:
my_string = "Hello"
my_list = ["Python", "Java", "C", "JavaScript", "Swift", "Kotlin"]
my_tuple = (4, 8, 15, 16, 23, 42)
You’ll use the string, list, and tuple above in the following examples.
You create empty strings, lists, and tuples either by using literal values or object initializer syntax:
empty_string = ""
another_empty_string = str()
empty_list = []
another_empty_list = list()
empty_tuple = ()
another_empty_tuple = tuple()
Accessing Individual Elements of a Sequence
Python uses array index notation to access elements of a sequence, where the first element’s index is 0
. For example:
my_string[1] # 'e'
my_list[0] # 'Python'
my_tuple[2] # 15
Python uses negative indexes to access sequence elements starting from the end, where the index for the last item is -1
, the index for the second-last item is -2
, and so on. For example:
my_string[-1] # 'o'
my_list[-2] # 'Swift'
my_tuple[-3] # 16
Accessing Slices of a Sequence
Python has a syntax for accessing a slice, a smaller sequence, from a string, list, or tuple. The simplest version of the slice syntax is sequence[start:stop]
. For example:
my_string[0:3] # Hel
my_list[2:4] # ['C', 'JavaScript']
my_tuple[1:3] # (8, 15)
You can use negative indexes to get slices:
my_string[-4:-2] # 'el'
my_list[-3:-1] # ['JavaScript', 'Swift']
my_tuple[-5:-3] # (8, 15)
You can omit the first index to start the slice from the beginning of the sequence or omit the second index to end the slice at the end of the sequence:
my_string[:2] # 'He'
my_list[2:] # ['JavaScript', 'Swift', 'Kotlin']
my_tuple[-3:] # (16, 23, 42)
Getting the Length of a Sequence
Use the len()
function to get a sequence’s length, the number of elements in the sequence:
len(my_string) # 5
len(my_list) # 6
len(my_tuple) # 6
Determining if a Given Item is in a Sequence
Use Python’s in
operator to test if a given item is contained within a sequence:
"h" in my_string # False
"Python" in my_list # True
42 in my_tuple # True
Determining How Many Instances of an Item Are in a Sequence
Use the count()
method to find out how many instances of an item are in a sequence:
# How many instances of `t`?
my_string.count("l") # 2
my_list.count("Python") # 1
my_tuple.count(99) # 0
Finding the First Instance of an Item in a Sequence
The index()
method returns the location of the first instance of a given item in a sequence, but only if it’s actually in the sequence:
my_string.index("l") # 2
my_list.index("Java") # 1
my_tuple.index(99) # ValueError
To avoid errors, use in
or count()
to test for the item’s presence before using index()
.
Merging Sequences
The +
operator can concatenate two sequences together:
my_string + my_string # 'HelloHello'
my_list + my_list
# ['Python', 'Java', 'C', 'JavaScript', 'Swift', 'Kotlin', 'Python', 'Java', 'C', 'JavaScript', 'Swift', 'Kotlin']
my_tuple + my_tuple
# (4, 8, 15, 16, 23, 42, 4, 8, 15, 16, 23, 42)
Repeating Sequences
The *
operator can repeat a sequence a number of times:
my_string * 3 # 'HelloHelloHello'
my_list * 2
# ['Python', 'Java', 'C', 'JavaScript', 'Swift', 'Kotlin', 'Python', 'Java', 'C', 'JavaScript', 'Swift', 'Kotlin']
my_tuple * 3
# (4, 8, 15, 16, 23, 42, 4, 8, 15, 16, 23, 42, 4, 8, 15, 16, 23, 42)
List Methods
Python’s lists have features beyond what you can do with other sequence types. The most-used ones are listed below.
Merging Two Lists
In Python, there are two ways to merge two lists, list_a
and list_b
. Both result in a new list starting with the elements of list_a
in order, followed by the elements of list_b
in order:
# Some flavors lists
flavors = ['vanilla']
sorted_flavors = ['choclate']
# Merging lists with +
lots_of_flavors = flavors + sorted_flavors
# Merging lists with `extend()`
flavors.extend(sorted_flavors)
for
Loops
Unlike for
loops in many other programming languages, especially those that borrow their syntax from C, Python’s for
loops are made not to change the value of an index variable but to iterate over a sequence and execute a block of code for each element in it.
Iterating Over Sequences
Here’s how you iterate over a list with a for
loop:
greeting = "Hello"
languages = ["Python", "Java", "C", "JavaScript", "Swift", "Kotlin"]
the_numbers = (4, 8, 15, 16, 23, 42)
for character in greeting:
print(f"The current character in {character}.")
for language in languages:
print(f"I'm now reading up on {language}.")
for number in the_numbers:
print(f"The current number is {number}.")
Like the while
loop, Python’s for
loop follows Python’s indentation rules.
Traditional(ish) for
Loops With the range()
Function
Sometimes, you want a loop to perform an action a specific number of times. Many other programming languages provide a for
loop to do this, using this syntax:
for (
set up counter variable;
exit condition ;
update counter variable)
Python’s built-in range()
function makes it possible to emulate this kind of for
loop by generating numbers as a sequence, which is what Python’s for
loops are designed to do.
If you provide range()
with a single integer n, a stop value, it creates a range
object that generates a sequence of numbers beginning with 0, increasing by one each time, and going up to, but not including, the stop value n.
for number in range(5):
print(number)
If you provide range()
with two integers, m, a start value and n, a stop value, it creates a range
object that generates a sequence of numbers beginning with the start value m, increasing by one each time, and going up to, but not including, the stop value n.
for number in range(-5, 5):
print(number)
If you provide range()
with three integers, m, a start value, n, a stop value, p, a step value, it creates a range
object that generates a sequence of numbers beginning with the start value m, increasing by the step value p each time, and going up to, but not including, the stop value n.
multiples_of_3 = range(-6, 20, 3)
for number in multiples_of_3:
print(number)
The Magic of enumerate()
Python’s built-in enumerate()
function, when wrapped around an object that you can iterate over, adds a counter:
nato_letters = ["alfa", "bravo", "charlie"]
for index, letter in enumerate(nato_letters):
print(f"{index}. {letter}") # 1. alfa / 2. bravo / 3. charlie
break
, continue
, and else
Like while
, Python’s for
loops also use the following keywords:
-
break
to exit the loop while in the loop body. -
continue
to go back to the beginning of the loop. -
else
to define a block of code that will execute only when the loop completes “normally” without executing thebreak
statement while in the loop.
Dictionaries
Python’s dictionaries are collections of key-value pairs, where you use a key to access the value associated with that key. They’re like JavaScript objects or what other languages might call associative arrays or hashmaps.
Here’s an example of assigning a dictionary to a variable:
employee = {
"name": "Alice",
"level": 5,
"years": 2,
"salary": 150_000
}
You can assign an empty dictionary to a variable with a dictionary literal or by instantiating a dictionary instance:
empty_dictionary = {}
another_empty_dictionary = dict()
Dictionary Keys and Values
Dictionary keys can be any type, as long as they are:
- Immutable: This includes numbers, strings, tuples containing only hashable values, and any object that doesn’t change during its lifetime. Lists, dictionaries, and sets, which the next lesson will cover, can’t be keys.
-
Hashable: Most of Python’s immutable types are also hashable. For example, they’re convertible into an integer value either by Python’s built-in
hash()
function or ahash()
method that it provides. Mutable types like lists, dictionaries, and sets are not hashable. - Unique (within the dictionary): Every key in a given dictionary must be unique.
Dictionary values can be any type.
Dictionary Methods and Operators
Here are the commonly-used dictionary methods and operators:
Getting Keys and Values as Separate Collections
The keys()
and values()
methods return specialized collection objects containing the dictionary’s keys and values:
crewmember = {
"name": "Bob",
"rank": "Captain",
"years": 3
}
print(f"keys:\n{crewmember.keys()}") # dict_keys(['name', 'rank', 'years'])
print(f"values:\n{crewmember.values()}") # dict_values(['Bob', 'Captain', 3])
keys
and values
aren’t lists but dict_keys
and dict_values
objects. You can’t access their individual elements until you convert them to lists first:
crewmember.keys[0] # TypeError: 'dict_keys' object is not subscriptable
keys_list = list(crewmember.keys)
keys_list[0] # 'name'
While you can’t directly access items in dict_keys
and dict_values
objects, you can use a for
loop to iterate over them:
for key in crewmember.keys():
print(f"- {key}") # r
for value in crewmember.values():
print(f"- {value}")
dict_keys
and dict_values
are dynamic view objects connected to their dictionary. Updating the dictionary also updates its dict_keys
and dict_values
objects.
Getting a Dictionary’s Keys and Values as Key-Value Tuples
The items()
method returns a dynamic view colleobject containing the dictionary’s keys and values as tuples:
For the following code:
employee = {
"name": "Alice",
"level": 5,
"years": 2,
"salary": 150_000
}
# dict_items([('name', 'Alice'), ('level', 5), ('years', 2), ('salary', 150000)])
print(employee.items())
items()
returns a dict_items
object, and you can iterate over its contents with a for
loop:
for item in employee.items():
print(item)
You can also convert a dict_items
object to a list using the list()
initializer.
Determining if a Given Value is in a Dictionary
There’s no built-in way to determine if a dictionary contains a given value. However, you can use the values()
method to get its values or the items()
method to get its key-value pairs and then see if they contain the value you want.
Regular Expressions
Working with regular expressions in Python requires importing the re
module, which is included with the standard Python distribution. Python’s import
statement is like those from many other languages:
import re
Working with regular expressions often requires string patterns containing backslash (\
) characters that should not be treated as the start of an escape sequence, such as \n
for the newline character. Python has r-strings, where backslashes are treated as literal backslash characters, for this purpose:
print(r"\n\t\n\t <-- These are NOT newlines or tabs!")
Python’s re
module has these key functions:
The re
modules use a standard set of special characters and expressions for regular expression pattern-matching:
You’ll see an example of regular expressions in the demo that follows this lesson.
Boolean Evaluations: Truthy and Falsy
Now that the major data types have been covered, it’s time to talk about how they’re evaluated as True
or False
by decision-making statements like if
/elif
/else
and while
and for
loops.
It’s clear that the following values and expressions evaluate as True
or False
:
True
False
True and True or False
some_value > 5
some_value > 5 and some_other_value != "stop"
It’s not obvious that all values and expressions also evaluate as True
or False
. In Python, there are the concepts of truthy and falsy where:
-
truthy refers to a value that evaluates to
True
. -
falsy refers to a value that evaluates to
False
.
The general rule is that if a value indicates absence, emptiness, or zero, it’s falsy and evaluates as False
. These include:
None
- Any numerical value for zero
- Any empty sequence or collection
On the other hand, if a value indicates presence, non-emptiness, or a non-zero value, it’s truthy and evaluates as True
. These include:
- Any object that isn’t
None
and meets one of the criteria below:- Any numerical value that isn’t zero
- Any string containing at least one character
- Any sequence or collection containing at least one item
Basic Functions
Here’s a definition of the simplest type of function — the type that takes any arguments and doesn’t return any values:
def say_hello():
"""Say hello to the user.""" # This is a docstring (see below)
print("Hey there! Welcome.")
Function definitions start with the def
keyword, short for define, followed by the function name, which in this case is say_hello()
. Like many other programming languages, the function name ends with parentheses.
When you run a code cell with one or more function definitions, those functions won’t execute unless some other code in that cell calls them. Once you run a code cell containing function definitions, those functions will remain “in scope” and available to any other code cells for as long as Jupyter runs.
Docstrings
You may have been wondering about the first line of say_hello()
’s body, shown below without the comment that followed it:
"""Say hello to the user"""
That’s a docstring, short for documentation string, and it’s a triple-quoted string literal on the first line in a function, method, class, or module. They’re for providing a concise explanation of the purpose, behavior, and usage of the function, method, class, or module.
Note: Lesson 2 of this course will cover defining methods and classes.
Docstrings are more than mere comments. As long as you put the docstring on the first line of the function, method, class, or module, it becomes accessible via the special built-in __doc__
property of those objects!
The following code prints the docstring for say_hello()
:
print(say_hello.__doc__) # "Say hello to the user."
Note:
__doc__
is part of a family of special Python properties and methods that begins and ends with double underscores (__
). They’re called dunder properties and dunder methods, where “dunder” is a shortening of “double underscore”.__doc__
can be pronounced “dunder doc.”
Passing Values to a Function
Python functions can take single arguments, as shown in the code below:
def say_oh_hi_with_name(name):
print(f"Oh hi, {name}!")
Like other languages’ functions, Python functions can also take multiple arguments:
def say_oh_hi_multiple_times(name, repetitions):
for count in range(repetitions):
print(f"Oh hi, {name}!")
Python functions support keyword arguments, where the function caller can specify which arguments are for which parameters:
say_oh_hi_multiple_times(repetitions=3, name="Lisa")
Keyword arguments, while they make a function call more verbose, have a couple of advantages:
- It’s clear which argument corresponds with which parameter.
- It lets you call a function without worrying about the order of arguments.
Finally, Python allows for default values for function parameters:
def say_oh_hi_multiple_times(name, repetitions=2):
for count in range(repetitions):
print(f"Oh hi, {name}!")
Note: For this course, the term argument refers to data passed to a function when calling it, and the term parameter refers to a variable in a function that stores the value of an argument passed to the function.
Returning a Value From a Function
Just like other programming languages’ functions, programs exit a function and return a single value with the return
statement:
def create_greeting(name):
return f"Greetings and salutations, {name}!"
Every function returns a value, but those that don’t have return
statements return the value None
.
Naming Functions
As with variables, there are generally accepted rules for naming functions in Python. The key points are:
- Use snake case! Function names should be all lowercase, with multi-word names using underscores to separate words. For example, use names like
my_function()
and notmyFunction()
. - Use only letters, numbers, and underscores in function names.
- Function names can start with a letter or underscore. They shouldn’t start with numbers.
- Names that begin or end with double underscores have special meaning in Python. Don’t use these names unless you know what you’re doing.
- Don’t use Python’s reserved keywords as function names.
Empty Blocks
In writing a program, you’ll often start with empty placeholder blocks of code that you intend to fill later.
Consider this JavaScript function:
// JavaScript
function placeholder() {
// TODO: Implement later
}
The body of the returnNothing()
function above is an empty code block, where the start and end of the block are clearly marked by visible characters, {
and }
, with nothing but whitespace and comments between them.
Python’s code blocks are marked by indentation, created using invisible characters. Because of this, there’s no definitive way to tell the difference between an empty block of code and a missing block of code.
If you try to define an empty function like this:
def placeholder():
# TODO: Implement later
You’ll get an error: SyntaxError: incomplete input
To solve this problem and allow you to create empty placeholder blocks, Python has the pass
keyword, which specifies an empty code block:
def placeholder():
# TODO: Implement later
pass
In the next demo, you’ll have some hands on with all you’ve learned about python