Lists
Here is how you make an empty list.
>>> x = []
We can add stuff to the end of the list using append
.
>>> x.append(1) >>> x.append(2) >>> x.append(3) >>> x [1, 2, 3]
Lists are heterogeneous. You can put items of any type into a list, including a list.
>>> x.append(4.5) >>> x.append([1,2,3, ["buffalo", "oryx"]]) >>> x [1, 2, 3, True, 4.5, [1,2,3, ["buffalo", "oryx"]]]
How do I get 4.5 out of the list?
>>> x[3] 4.5
A whole list resides at index 4.
>>> x[4] [1,2,3, ["buffalo", "oryx"]]
How do we get the buffalo out in the open?
First we see how to get the 1 out at the start of x[4]
>>> x[4][0] 1
Now we get the list out.
>>> x[4][3] 1
Whoa! Here comes the buffalo!
>>> x[4][3][0] 'buffalo'
Now see this!
>>> x[4][3][0][1:] 'uffalo'
Here is a nifty trick to get an arithmetic sequence of integers. It starts at 2 and ends before 100.
>>> q = list(range(2, 100, 7)) >>> q [2, 9, 16, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93]
You can get slices of lists in a manner identical to that of strings. This is a really nice parallelism. You should do some experimenting with this.
>>> q[:3] [2, 9, 16]
>>> q[0] = "hassenpfeffer" >>> q ['hassenpfeffer', 9, 16, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93]
List entries are lvalues, i.e. they behave like variables in that they can store stuff assigned to them.
Contrast that to strings.
>>> s = "abc" >>> s[0] = "q" Traceback (most recent call last): File "<stdin>", line 1, inTypeError: 'str' object does not support item assignment
Strings are immutable. Once you create a string, you cannot change it. You can only ask a variable pointing at it to point at some other string.
Let us remind ourselves about state. A string's state is its character sequence. A list's state is the items it contains along with the order in which they are present. Lists are mutable: appending a new item changes the state of a list.
Now let us use the sort
method.
>>> roster = ["deng", "scraeder", "de los Reyes", "mcginnis"] >>> roster.sort() ['de los Reyes', 'deng', 'mcginnis', 'scraeder']
It appears to have alphabetized the list. Now I perpetrate a wee bit of mischief.
>>> roster.append("Ketola") >>> roster.append("Battacharya") >>> roster.append("Montambo") >>> roster ['de los Reyes', 'deng', 'mcginnis', 'scraeder', 'Ketola', 'Battacharya', 'Montambo'] >>> roster.sort() ['de los Reyes', 'deng', 'mcginnis', 'scraeder', 'Ketola', 'Battacharya', 'Montambo']
What happened? All of the capitalized names come first! This is because the ordering is not alphabetical; rather it is asciicographical. In sorting the list, "alphabetization" is done by the ASCII value of the characters.
So far, you have lerned about one builtin Python function,
len
, which gives the length of a sequence. Now
you will learn about another, ord
. This gives you
the ASCII (byte) value of any character.
>>> ord("a") 97 >>> ord("b") 98 >>> ord("A") 65
Word Origin Time The root "lex" means "word". A lexicon is a dictionary. A lexicographical ordering is a dictionary ordering.
Here is something idiotic.
idiot = [1, True, "cows", [3,4,5]] >>> idiot.sort() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '<' not supported between instances of 'str' and 'bool'
It only makes sense to sort homogenous lists containing items that are sortable.
Numerical lists can be sorted lexicographically.
>>> x = [[1,2,3], [2,1,6],[4],[-3,6,-1]] >>> x.sort() [[1, 2, 3], [2, 1, 6], [4], [-3, 6, -1]]
A Brief Interlude: Relational Opeators
The relational operators are infix binary operators that return a boolean value.
Operator | Meaning |
---|---|
< | less than |
<= | less than or equal to |
> | less than |
>= | less than or equal to |
== | isequalto |
!= | not equals |
is | returns True if the
two operands are the same object. It checks for equality of identity. |
No surprises here.
>>> >>> 5 > 6 False >>> 5*5 == 25 True >>> 5 < 6 True >>> 5 >= 6 False >>> 5 <= 6 True >>> 5 != 6 True
Now let's talk about is
.
>>> x = "quack" >>> y = "quack" >>> x is y True
No apparent surprise here. Now let's do this.
>>> >>> >>> moo = [] >>> foo = [] >>> moo == foo True >>> moo is foo False
What happened? We know strings are immutable. Pytho does something called pooling. Small strings generated during a program are placed in an area of memory called the string pool. This does not get garbage collected. But if an orphaned string appears again in the program, the object in the pool is used. This practice confers many advantages.
Lists, however, are mutable. Look what happens here.
>>> original = [] >>> copy = original >>> original is copy True >>> copy.append("foo") >>> copy ['foo'] >>> original ['foo']
Since original
and copy
point at the
same object, if one makes changes, the other sees it.
Here is a trick for copying a list.
>>> a = [1,2,3] >>> b = a[:] >>> b [1, 2, 3] >>> b is a False
We have two independent copies of the list. Here is more evidence of same.
>>> a.append(4) >>> a [1, 2, 3, 4] >>> b [1, 2, 3] >>>
Cast a string to a list and it "explodes" the string into a list of characters.
>>> >>> s = "abcdefg" >>> list(s) ['a', 'b', 'c', 'd', 'e', 'f', 'g']
Can we go the other way?
>>> a [1, 2, 3, 4] >>> str(a) '[1, 2, 3, 4]'
Any Python object can be cast to a string.
>>> str(4) '4' >>> str(4.5) '4.5' >>> str(True) 'True' >>> str("foo") 'foo'
>>>
>>>
>>>
>>>
>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>