Python uses three style of special enclosing delimiters. These are what the Python documentation calls them:
{} braces # Sometimes called curly brackets elsewhere.
[] brackets # Sometimes called square brackets elsewhere.
() parentheses # Sometimes called curved brackets elsewhere.
Holding more than one thing
What happens if we want to store more than one thing?
What happens if we want to store 10000 data points? We don't want to have to call each by a new name.
Languages generally have variables that are arrays: one variable that can store multiple things with one name and a numerical index. Here's one in Java:
Assignment:
array_name[3] = 21;
Subscription (sometimes called indexing):
System.out.print (array_name[3]);
Out of range
Depending on the language and data stored, the array will either refer to a space in memory where all the literals are stored, or will contain pointers (memory addresses) or references (linked labels) to their locations in memory (in Python it is generally the later).
Attempts to read a cell that doesn't exist will usually generate some kind of error message (usually "Index out of range/bounds" or similar) and end the program.
Arrays
As arrays can be very large, they usually require manifest typing - you have to say what they are going to hold (and sometimes how large they will be) to build them.
Python arrays need manifest typing. Python arrays are in a special module. You'd make one like this:
import array
a = array.array('i',[0,0,0,0]) # Signed int type 'i'
a.insert(3, 21)
print(a[3])
Unlike many arrays, you don't need to say how big it will be.
Arrays
Arrays are very efficient: they are memory optimised for space and often for searching.
However, in general in most languages they aren't very easy to use:
You can only put pre-defined data types in them (usually just one)
In most languages (though not Python) they have a fixed size
(in Python, stuff just gets added to the end whatever the index, though attempts to read non-existent cells still generates errors).
Because of this, most languages have wrappers for arrays that make them more flexible. In Python, these objects are called Containers, and much more used than arrays.
Containers
The container depends on how data is to be accessed, and whether it can be altered or not.
We will mainly be dealing with those in bold.
Data changeable:"Mutables"
Data fixed: "Immutables"
Access by position:"Sequences"
List
Tuple; String; Bytes
Access by name: "Mappings"
Dictionary
Named tuple
Access by checking existence: "Sets"
Set
Frozen set
Mutability
Mutability is whether data can be changed after it is stored in an object.
Immutable objects are more efficient, as the computer can optimise around them guaranteed they won't change. Obviously, though, not being able to change them is limiting.
Numbers and strings are immutable, though they may not seem it: if you assign a new value to a pre-existing label, the value is created anew.
Of the containers, strings and tuples are immutable. We'll see that a) strings are containers, and b) that tuples can be immutable, yet contain mutable objects.
Dictionaries, sets, and lists are mutable.
Sequences
Have the advantage of being a sequence (usually the sequence as added, but potentially ordered).
Their length is found with a builtin function, thus:
len(sequence_name)
a = len(seq) #e.g
Just like arrays, we refer to the values in them using a name and position index:
name[i] # Where i is an int.
print(seq[2]) # e.g.
All indices start with zero and go to len(sequence_name) - 1
0
1
2
...
len(sequence) - 1
Sequences
Tuples: immutable sequence of objects, either literal-style or more complicated objects.
Lists: mutable sequence of objects, either literal-style or more complicated objects.
Both can contain other sequences as their objects, and both can contain mixed types of object, so, for example ints and strings.
Tuples
Tuples are produced by the comma operator if used without [] {} enclosers. For example:
a = 2,3
Frequently they are inside (), but this is only necessary for making the empty tuple:
a = (2,3)
a = ()
The following is a tuple with one element (the documentation calls this a singleton, though beware this has other, more general meanings):
a = 2,
You can also use a constructor function:
a = tuple(some_other_collection)
Tuples
You can also add and multiply tuples (but not subtract from them or divide):
>>> a = 1,2,3
>>> a = a + (4,) # or a += 4,
>>> a
(1, 2, 3, 4)
>>> a = 1,2,3
>>> a = a*2 # or a *= 2
>>> a
(1,2,3,1,2,3)
Subscription
You can get values out, thus:
a[0] # First
a[len(a) - 1] # Last
But also:
a[-1] # Last
a[-len(a)] # First
Negatives count back from the end (essentially negatives get len()added to them).
Packing
Forcing multiple answers into a sequence is known as 'packing'.
Example: the divmod() builtin function returns a tuple (a // b, a % b)
>>> c = divmod (9,2)
>>> type(c) # c is automatically made tuple type
>>> c[0] # subscription, cell 0
4 # 9//2
>>> c[1] # subscription, cell 1
1 # 9%2
Unpacking
Unpacking is splitting a sequence across variables:
>>> a = (1,2)
>>> b, c = a
>>> b
1
>>> c
2
There must be the right number of variables to unpack into.
Relatively rare in other languages, so feels Pythonic.
Packing/Unpacking
This packing/unpacking means you can assign multiple variables at once:
a, b = 1, 2
But also means you can do this:
a, b = divmod(9,2)
If you see two variable names with a comma between, they are usually being assigned some unpacked sequence.
You can find out what type with:
>>> c = divmod(9,2)
>>> type(c)
or
>>> type(divmod(9,2))
Which returns the sequence (here a tuple) and passes it straight to the type function.
Example
>>> # Fibonacci series
>>> # the sum of two elements
defines the next
>>> a, b = 0, 1
>>> while b < 10:
... print(b)
... a, b = b, a+b
Ranges
Ranges are a special type of immutable sequence.
range(start, stop, step) # Elements in italics optional
Start; stop; step should be ints.
Default for start = 0
Default for step = 1
Generates numbers up to but not including stop.
range(4) # generates 0,1,2,3
Note how this is the same as sequence indices - this will come in useful.
range(2,8,2) generates 2,4,6
range(0,-5,-1) generates 0,-1,-2,-3,-4
Tuple constructor
One way to make a tuple is thus:
a = tuple(x) # Where x is a sequence or producer of a sequence
>>> a = tuple(range(5))
>>> a
(0,1,2,3,4)
Note you can't just assign a label:
>>> a = range(5)
>>> a
'range(0,5)'
>>> type(a)
<class 'range'>
Sequence functions
min(a) # Smallest item in a.
max(a) # Largest item in a.
a.index(x,i,j)
# Index of the first occurrence of x in a
#(at or after optional index i and before index j).
a.count(x) # Counts of x in a.
any(a)
# For a sequence of Booleans, checks whether
# any are true. Returns as soon as it finds
# one (likewise, because of conversion,
# whether any numbers are != 0)