Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Project: SageDays78
Views: 431

Introduction to Python

using sage


Sage + Python = Awesomeness

First things first:

Tabbing & Questions

If you don't know what a function does, type the function, add a ? and hit tab for a quick description.

Try typing:

fibonacci?
# Try it here! fibonacci?

Second:

Data Types

Luckily there are a finite number of data types in Python. This list includes
  • Booleans
  • Integers
  • Floats
  • Strings
  • Sets
  • Lists
  • Tuples
  • Dictionaries
Python is a dynamic language, so there is no need to declare what variable type you are using. You can also change the type of your variables. To know what type a variable is you can just ask for it's type using the type function. Or you can ask directly if the object is of a certain type using isinstance.

Full details can be found in the python docs.
a = "123" type(a) a = 123 type(a)
<type 'str'> <type 'sage.rings.integer.Integer'>
isinstance(a, Integer) isinstance(a, str)
True False

Booleans

bool has one of two values: True and False.

There are three boolean operators: and, or, & not.

You can convert something into a boolean by the bool function.

type(True)
<type 'bool'>
bool(1) bool(0) bool(-1)
True False True
True and False
False
not True
False
False or True
True

Integers/Floats

int is the python built-in integer type. The problem with the python version is the integer conversion problem. Due to this restriction, Sage uses its own type called Integer.

float is the python built-in rational number type. Due to similar restrictions, Sage uses the RealLiteral type.

int(5)/int(2)
2
type(1) type(1.2)
<type 'sage.rings.integer.Integer'> <type 'sage.rings.real_mpfr.RealLiteral'>

Strings

The str type is fairly common. You can use single or double quotes. Additionally you can use triple quotes if you want a multi-line string. You can also fill a string using dictionary substitutions as can be seen in the following example.

aram = 'Aram' print """Hello %s, You're a pretty cool person. - %s """ % ('human', aram)
Hello human, You're a pretty cool person. - Aram
print a, "factors into", a.factor()
123 factors into 3 * 41
print str(a) + " factors into " + str(a.factor())
123 factors into 3 * 41

Sets, lists, tuples, and dictionaries

Because, why not.
  • set - is a set of items with no multiplicites or order.
  • list - is an ordered list of items
  • tuple - is the same as a list, but it is immutable (it cannot be changed).
  • dict - Is an associative array which associates values with keys.

Some basic commands

Constructing stuff

S = set([1,2,3]) L = [1,2,3] T = (1,2,3) D = {2:1, 3:2, 4:3} S L T D
set([1, 2, 3]) [1, 2, 3] (1, 2, 3) {2: 1, 3: 2, 4: 3}
set([1]) [1] {1:2}
set([1]) [1] {1: 2}
(1) (1,2)
1 (1, 2)
(1,)
(1,)

How many stuff does it have?

Use the len function.
len(S) len(L) len(T) len(D)
3 3 3 3

Is this object present?

Use the in operator.
Note: The in operator for dictionaries looks at the keys!
S = set([1,2,3]) L = [1,2,3] T = (1,2,3) D = {2:1, 3:2, 4:3} 1 in S 1 in L 1 in T 1 in D
True True True False
4 not in S 4 not in L 4 not in T 4 not in D
True True True False

How do I access elements?

Use square brackets to access individual items. For dictionaries you use the key. For lists and tuples the counting begins at 00. Sets have no order so you can't "access" things.
L = [1,2,3] T = (1,2,3) D = {2:1, 3:2, 4:3} L[0] T[0] D[2]
1 1 1

Can I modify things?

Only lists and dictionaries! Tuples are immutable, so they can't be altered.
L[0] = 5 D[2] = 5 L D
[5, 2, 3] {2: 5, 3: 2, 4: 3}

How do I add new things?

There are many ways my young padawan.
Sets - Use the add function
Lists - You can append a list at the end, extend a list with another list, or just plain add two lists together.
Tuples - They are immutable, so we can't alter them! We can add two of them together and create a new tuple though.
Dictionaries - Just add a new key and put in a value.
S = set([1,2,3]) S.add(2) S.add(4) S
set([1, 2, 3, 4])
L = [1,2,3] L2 = ["a", "b"] L3 = [(1,2), (4,5)] L.append(4) L.extend(L2) L L4 = L2 + L3 L4
[1, 2, 3, 4, 'a', 'b'] ['a', 'b', (1, 2), (4, 5)]
T = (1,2,3) T2 = (0,0) T3 = T + T2 T3
(1, 2, 3, 0, 0)
D = {2:1, 3:2, 4:3} D[10] = fibonacci(10) D[(3,2,1)] = Permutation([3,2,1]) D
{2: 1, 3: 2, 4: 3, 10: 55, (3, 2, 1): [3, 2, 1]}
Note: For lists we can't add additional items like we do in dictionaries.
L[10] = fibonacci(10)
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-6.10/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 905, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> IndexError: list assignment index out of range
Note: We also can't add mutable items as keys for dictionaries.
D[[1]] = 'fail'
Error in lines 1-1 Traceback (most recent call last): File "/projects/sage/sage-6.10/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 905, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'list'

Russell's paradox

Sets of sets can't happen
S1 = set([1,2,3]) S2 = set([S1]) S2
Error in lines 2-2 Traceback (most recent call last): File "/projects/sage/sage-6.10/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 905, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> TypeError: unhashable type: 'set'
S1 = frozenset([1,2,3]) S2 = set([S1]) S2
set([frozenset([1, 2, 3])])
Exercise: Look at the following code and make a guess as to what will be displayed.
L = [1,"z",3,4,5] L.append("c") L = L + [9,10] L[6]
9

But I added too much! How do I delete things I don't want?

S = set([1,2,3]) S.discard(2) S
set([1, 3])
L = [1,2,3,4,5] del L[1] poppedItem = L.pop(0) L.remove(3) L poppedItem L.remove(3)
[4, 5] 1
Error in lines 7-7 Traceback (most recent call last): File "/projects/sage/sage-6.10/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 905, in execute exec compile(block+'\n', '', 'single') in namespace, locals File "", line 1, in <module> ValueError: list.remove(x): x not in list
L = [1, 2, 3, 2] L.remove(2) L
[1, 3, 2]
L2 = [1,2,3,4,5] L2 = L2[1:3] L2
[2, 3]
T = (1,2,3,4,5) T = T[1:3] T
D = {2:1, 3:2, 4:3} del D[3] poppedItem = D.pop(4) D
{2: 1}
Some other useful commands (Lists only!):
  • sort
  • reverse
L = [5,4,1,2,3] L.sort() L
[1, 2, 3, 4, 5]
L = [5,4,1,2,3] L.reverse() L
[3, 2, 1, 4, 5]

Some basic commands

Operation set list tuple dict
Construction set([]) [] () {}
One element construction set([1]) [1] (1,) {1:1}
Size len(set) len(list) len(tuple) len(dict)
Contains x in set x in list x in tuple key in dict
Accessing entries - list[0] tuple[0] dict[key]
Adding stuff set.add(x) list.append(x)
list.extend(list2)
list3 = list1 + list2
tuple3 = tuple1 + tuple2 dict[key] = x
key must be immutable
Deleting stuff set.discard(item) list.pop(i)
del list[i]
list = list[start:end]
list.remove(value)
tuple = tuple[start:end] dict.pop(key)
del dict[key]
Exercise:
  1. Create the list [5,1,3,6,7,2,12].
  2. Remove the element 12.
  3. Add the element 4.
  4. Sort the list and reverse it.
# Try it out!

The modification problem.

Or things that should be illegal.
Changing lists and dictionaries can have unintended consequences.
L = ["a", "b", "c"] L2 = [L, L] L2
[['a', 'b', 'c'], ['a', 'b', 'c']]
L.append("d") L2
[['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd']]
L = ["a", "b", "c"] L2
[['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd']]
L2[0].remove("c") L2
[['a', 'b', 'd'], ['a', 'b', 'd']]

Stop this nonsense! How do we fix this?

deepcopy to the rescue!

L = ["a", "b", "c"] L2 = [deepcopy(L), deepcopy(L)] L2
[['a', 'b', 'c'], ['a', 'b', 'c']]
L.append("d") L2
[['a', 'b', 'c'], ['a', 'b', 'c']]

The None type

If you want to set a variable but don't want to set it as any particular type, you can use None

v = None v

Ranges

Lists made easy

Ranges allow us to make numerical lists easily. We use the range function to construct a range.

range?
File: Docstring : range(stop) -> list of integers range(start, stop[, step]) -> list of integers Return a list containing an arithmetic progression of integers. range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0. When step is given, it specifies the increment (or decrement). For example, range(4) returns [0, 1, 2, 3]. The end point is omitted! These are exactly the valid indices for a list of 4 elements.
range(1,10)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
range(1,10,2)
[1, 3, 5, 7, 9]
range(20,1,-1)
[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2]
Exercise: Use range to construct the list of even numbers between 11 and 4040 (including 4040).
Bonus: Put it in reverse order.
# Try it out! range(2,41,2) range(40,1,-2)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40] [40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2]

Third parts the charm:

Control Flows

  • if - Does something if the condition is true.
  • for - Loops through a range of objects.
  • while - Keeps looping until condition is false.
For more details you can visit the control flow page on the Python docs.

Quick aside: Comparisons

  • or    and    not - Boolean operators
  • == - Equal
  • != - Not equal
  • <   >   <=   >= - Inequalities
  • is - Object identity
  • is not - Negated object identity

if

with its siblings elif and else.
if 2 in (1,2,3,4): print "2 is in our tuple!"
2 is in our tuple!
R = range(1,10,2) if 2 in R: print "2 is in range." elif 4 in R: print "4 is in range." else: print "By faulty induction our range is only odd numbers."
By faulty induction our range is only odd numbers.

for

for i in set([3,2,1]): print i
1 2 3
for i in range(1,5): print i
1 2 3 4
for i in range(1,10): if i % 2 == 0: print i
2 4 6 8
for i in range(1,10): if is_prime(i): print i
2 3 5 7
Exercise: Use a for loop to print out all the non-even primes from 11 to 100100.
# Try it yourself for i in range(1,100): if is_prime(i) and i % 2 != 0: print i
3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

while

C = 3 while C != 1: print C if C % 2 == 0: C /= 2 else: C = C*3 + 1
3 10 5 16 8 4 2

for and list

The super team
We can use for loops in order to create super awesome lists.
[i^2 for i in range(1,10)]
[1, 4, 9, 16, 25, 36, 49, 64, 81]
We can even combine if statements!
[i for i in range(1,50) if i%7 == 0 or i%5 == 0]
[5, 7, 10, 14, 15, 20, 21, 25, 28, 30, 35, 40, 42, 45, 49]
And take sums!
sum([p for p in range(1,10) if is_prime(p)])
Exercise: Find the sume of the non-even primes from 11 to 100100.
# Try it yourself!

Wait, it gets better.... Nesting!

We can nest these lists in order to construct lists of tuples, dictionaries, matrices, etc.
[(x,y,z) for x in range(1,3) for y in range(1,3) for z in range (1,3)]
[[i^j for j in range(1,3)] for i in range(1,5)]
matrix([[i^j for j in range(1,3)] for i in range(1,5)])

These special lists also allow us to grab the keys/values of dictionaries!

D = {2:1, 3:2, 4:3} [value for value in D.itervalues()]
[key for key in D.iterkeys()]
[(key,value) for key,value in D.iteritems()]

Integers vs ints

Revisited
matrix(QQ, [[i/j for i in range(1,10)] for j in range(1,10)])
matrix(QQ, [[i/j for i in srange(1,10)] for j in srange(1,10)])

Part 222^2:

Functions

Functions are defined using the def statement. We can return things from functions using the return keyword.
def f(x): return x^2 f(2)

Recursion - Catalan Numbers

C0=1C_0 = 1
Cn=2(2n1)n+1Cn1C_{n} = \frac{2(2n-1)}{n+1} C_{n-1}
def catalanNumber(x): if x == 0: return 1 else: return (2 * (2 * x - 1) / (x+1)) * catalanNumber(x-1) [catalanNumber(n) for n in range(0,10)]

Complicated recursion - Catalan Numbers part 2

C0=1C_0 = 1
Cn=i=0n1CiCn1iC_n = \sum_{i = 0}^{n-1} C_{i} C_{n-1-i}
def catalanNumber(x): if x == 0: return 1 else: return sum([ (catalanNumber(i) * catalanNumber(x-1 - i)) for i in range(0,x)]) [catalanNumber(n) for n in range(0,10)]
Exercise: Create a function for the fibonacci series and display the first 2020.
# Try it!

Functions can also have default values.

# By default we choose 1 def choose(n, k = 1): return binomial(n,k) choose(5) choose(5,2)

Functions can also return multiple values if desired.

def fibAndCat(n): return fibonacci(n), catalan_number(n) F, C = fibAndCat(5) F C
[fibAndCat(i) for i in range(0,10)]

Digraphs!

Sage allows us to construct digraphs using dictionaries. Let's take a sidestep and look at how to construct digraphs and some operations we can do on them.

D = {0:[1,2,3], 1:[0,3], 2:[3,4], 4:[5,5,5,1], 5:[5]} G = DiGraph(D) G.plot()
G.adjacency_matrix()
Exercise: Plot your favourite digraph.