Basic types
In python, there are many built-in types.
The most common basic types are int
, float
, bool
and str
.
-
# immutable a = int('45.9') b = 15 // 4 c = 4387372
-
# immutable a = float(2) b = 32 / 2 c = 2.8
-
# immutable a = bool('') b = a < 1 c = False
-
# immutable a = str(True) b = 'hello' c = 'hello'.upper()
Strings are a bit different because they are sequences of characters and so they are more interesting.
String manipulation
Strings, are immutable sequences of characters, a form of compound data type. These methods never change the value of a string, they return new string instances.
-
'hello world'.upper()
-
'HELLO WORLD'
-
'hello world'.capitalize()
-
'Hello world'
-
'hello world'.title()
-
'Hello World'
-
'hello world'.split()
-
['hello', 'world']
-
'hello world'.split('o')
-
['hell', ' w', 'rld']
-
'hello'.join('world')
-
'whelloohellorhellolhellod'
see more in the python documentation
Immutability
The int
, float
, bool
, str
and tuple
data types are immutable.
This means that instances of these types cannot be modified.
a = 100000000
a += 1
Though it may sometimes seem like they are being modified, in fact, new pyObjects are created in memory.
Compound types
Compound types provide us with structures to group data together. They tend to be mutable, except for strings and tuples.
-
# immutable a = tuple('hello') b = (1.0, 'hello') c = ('hello', ) d = a[:3]
-
# mutable a = list('hello') b = [1.0, 'hello'] c = a + b d = 'hello world'.split()
-
# mutable a = dict((('a', 2), ('b', 4))) b = { 'a': 1.0, 'b': 'hello' }
-
# mutable a = set('hello') b = {1.0, 'hello', 'e', 'o'} c = a | b d = a & b e = a - b
Combining compound types
Compound types can easily be combined to produce the data structures you need.
player_data = {
"health": 82,
"attack": 21,
"shield": 5,
"magic": 76,
"speed": 45,
"inventory": [
{ "name": "blue potion", "type": "health", "power": 6 }
],
"check-point": 84
}
sword = { "name": "massive sword", "type": "weapon", "power": 9 }
player_data['inventory'].append(sword)
used here
More built-in types
Many more exotic types exist but we don’t really need to know about them all. We have seen examples of some of these. You will often find yourself using them without realising it.
-
type(None).__name__
-
'NoneType'
-
type(print).__name__
-
'builtin_function_or_method'
-
type(''.center).__name__
-
'builtin_function_or_method'
-
type(reversed('hello')).__name__
-
'reversed'
-
type(type(1)).__name__
-
'type'
The key point is that everything is an object, everything has a type.
Sequences
Sequences (such as str
, tuple
and list
) store items in a particular order and allow for indexing and slicing.
-
Indexing
-
('I', 'just', 'wanna', 'tell', 'you', 'how', "I'm", 'feeling')[2]
-
'wanna'
-
'Gotta make you understand'[-1]
-
'd'
-
Slicing
-
['I', 'just', 'wanna', 'tell', 'you', 'how', "I'm", 'feeling'][1::2]
-
['just', 'tell', 'how', 'feeling']
-
'Gotta make you understand'[::4]
-
'Gakonsd'
Compound statements
Compound statements control the flow and context of code execution within code blocks defined using indentation.
-
while input('Yes? [y/n]: ') == 'y': print("yes!")
-
with open('filename.txt', 'r') as file: data = file.read()
-
if a: print(a)
-
for ch in 'hello': print(ch)
-
def play_game(): print('fun!')
-
try: guess = int(input('guess: ')) except ValueError: print("That's not a number!")
-
class Guess: def __init__(self, actual): self.value = input('guess: ') self.correct = self.value == actual
Looping over sequences with for
A for
loop will run the code block once for each iterated value.
The for
syntax requires a named variable, followed by the keyword in
, followed by an iterable object.
Sequences are iterable, so they can be used in a for
loop.
things_ill_never_do = ["give you up", "let you down", "run around and desert you"]
for this_thing in things_ill_never_do:
print(f"Never gonna {this_thing}")
Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
if
and while
The if
and while
clauses require a conditional statement which is evaluated for truth.
If the statement evaluates to True
then the block is executed, otherwise the block is skipped.
-
if True: print('this always happens') else: print('this never happens') print('followed by this')
-
count = 0 while True: count += 1 print(f'continuously happens ({count})') print('this never happens')
The while
loop will repeat until the conditional evaluates to False
.
The above example using while True:
is an infinite loop which can only be exited using the break
keyword.
The continue
keyword can be used to skip to the next loop.
Both break
and continue
can be used in for
loops too.
-
count = 0 while True: count += 1 if count > 10: break;
-
for i in range(200): print('every time') if i < 100: continue print("from 100 only")
Iterables
An iterable is an object capable of returning its members one at a time. If it makes sense to iterate over something, then it’s probably an iterable.
All sequences are iterable, plus the
dict
type and file-like objects.
for key in player_data:
print(f'{key}: {player_data[key]}')
But also methods will return iterables, such as dict.items()
which iterates over the (key, value)
pairs.
This is often more convenient than looping over the keys alone.
for key, value in player_data.items():
print(f'{key}: {value}')
player_data
from here
Functions
The def
keyword allows us to define a function with a list of arguments in parentheses.
Functions allow for statements to be collected together into a reusable recipe with a custom name.
def input_yes_no(prompt):
result = input(f"{prompt} [y/n]: ")
return result.lower().startswith('y')
Try to keep your functions small, like this. A function should usually do just one thing.
Calling the function is simple.
while True:
print('This is a fun game!')
if not input_yes_no('Would you like to play again?'):
break
print('Again? OK!!')