# Python introduction¶

Python is used as user interface in sagemath.

We can define variables, like variable ‘a’ with integer value ‘2019’. The last expression of some input cell is represented in an output cell.

In [1]:
a = 2019
a

Out[1]:
2019

Only the last one; so the first ‘a’ will not be represented.

In [2]:
a
a

Out[2]:
2019

You can always enforce a string representation with ‘print()’.

In [3]:
print(a)
a

2019

Out[3]:
2019

You also assign two variables simultaneously:

In [4]:
a, b = 2019, 426


String formatting is also provided by python:

In [5]:
print('{} and {}'.format(a, b))

2019 and 426


An example algorithm (Euclidean algorithm) with our first control structure: a while loop

In [6]:
a, b = 2019, 426
n, m = a, b

while n != 0:
m, n = n, m % n

print('The gcd of {} and {} is {}'.format(a, b, m))

The gcd of 2019 and 426 is 3


We can encapsulate this algorithm in a function. ‘def’ introduces a function. ‘n’ and ‘m’ are parameters. ‘return’ specifies the return value.

In [7]:
def our_gcd(n, m):
while n != 0:
m, n = n, m % n
return m


Call the function named ‘our_gcd’

In [8]:
print(our_gcd(a, b))

3


A partial verification test for ‘our_gcd’:

In [9]:
# a for-loop iterates from 1 (incl.) to 100 (excl.): 1, 2, …, 99
for i in range(1, 100):
# ‘our_gcd’ is the function defined above, ‘gcd’ is provided by sagemath (NOT python!)
if our_gcd(i, 56) != gcd(i, 56):
# raising an exception halts the program and prints an error message
raise ValueError('our_gcd yields invalid result for {} and {}'.format(i, 56))


You can also rename/assign functions and all objects in python can be printed:

In [10]:
glt_gcd = our_gcd
print(glt_gcd)

<function our_gcd at 0x7fb6e2c0c488>


A simple function with a docstring (i.e. function documentation string). A docstring is given if the first expression is an unassigned string.

In [11]:
def inc(a):
"""Returns the argument incremented by one"""
return a + 1


‘assert’ can be used to test invariants:

In [12]:
assert inc(41) == 42


‘help’ shows the function documentation with the docstring:

In [13]:
help(inc)

Help on function inc in module __main__:

inc(a)
Returns the argument incremented by one



With sagemath, an appended question mark also shows the documentation:

In [14]:
gcd?

Signature:      gcd(a, b=None, **kwargs)
Docstring:
The greatest common divisor of a and b, or if a is a list and b is
omitted the greatest common divisor of all elements of a.

INPUT:

* "a,b" - two elements of a ring with gcd or

* "a" - a list or tuple of elements of a ring with gcd

Additional keyword arguments are passed to the respectively called
methods.

OUTPUT:

The given elements are first coerced into a common parent. Then,
their greatest common divisor *in that common parent* is returned.

EXAMPLES:

sage: GCD(97,100)
1
sage: GCD(97*10^15, 19^20*97^2)
97
sage: GCD(2/3, 4/5)
2/15
sage: GCD([2,4,6,8])
2
sage: GCD(srange(0,10000,10))  # fast  !!
10

Note that to take the gcd of n elements for n not= 2 you must put
the elements into a list by enclosing them in "[..]".  Before
https://trac.sagemath.org/4988 the following wrongly returned 3
since the third parameter was just ignored:

sage: gcd(3, 6, 2)
Traceback (most recent call last):
...
TypeError: gcd() takes ...
sage: gcd([3, 6, 2])
1

Similarly, giving just one element (which is not a list) gives an
error:

sage: gcd(3)
Traceback (most recent call last):
...
TypeError: 'sage.rings.integer.Integer' object is not iterable

By convention, the gcd of the empty list is (the integer) 0:

sage: gcd([])
0
sage: type(gcd([]))
<type 'sage.rings.integer.Integer'>
Init docstring: x.__init__(...) initializes x; see help(type(x)) for signature
File:           ~/sage/local/lib/python2.7/site-packages/sage/arith/misc.py
Type:           function


With sagemath, two appended question marks shows the source code (might be cython source code):

In [15]:
gcd??

Signature: gcd(a, b=None, **kwargs)
Source:
def gcd(a, b=None, **kwargs):
r"""
The greatest common divisor of a and b, or if a is a list and b is
omitted the greatest common divisor of all elements of a.

INPUT:

-  a,b - two elements of a ring with gcd or

-  a - a list or tuple of elements of a ring with
gcd

Additional keyword arguments are passed to the respectively called
methods.

OUTPUT:

The given elements are first coerced into a common parent. Then,
their greatest common divisor *in that common parent* is returned.

EXAMPLES::

sage: GCD(97,100)
1
sage: GCD(97*10^15, 19^20*97^2)
97
sage: GCD(2/3, 4/5)
2/15
sage: GCD([2,4,6,8])
2
sage: GCD(srange(0,10000,10))  # fast  !!
10

Note that to take the gcd of n elements for n \not= 2 you must
put the elements into a list by enclosing them in [..].  Before
:trac:4988 the following wrongly returned 3 since the third parameter
was just ignored::

sage: gcd(3, 6, 2)
Traceback (most recent call last):
...
TypeError: gcd() takes ...
sage: gcd([3, 6, 2])
1

Similarly, giving just one element (which is not a list) gives an error::

sage: gcd(3)
Traceback (most recent call last):
...
TypeError: 'sage.rings.integer.Integer' object is not iterable

By convention, the gcd of the empty list is (the integer) 0::

sage: gcd([])
0
sage: type(gcd([]))
<type 'sage.rings.integer.Integer'>

TESTS:

The following shows that indeed coercion takes place before computing
the gcd. This behaviour was introduced in :trac:10771::

sage: R.<x>=QQ[]
sage: S.<x>=ZZ[]
sage: p = S.random_element(degree=(0,10))
sage: q = R.random_element(degree=(0,10))
sage: parent(gcd(1/p,q))
Fraction Field of Univariate Polynomial Ring in x over Rational Field
sage: parent(gcd([1/p,q]))
Fraction Field of Univariate Polynomial Ring in x over Rational Field

Make sure we try QQ and not merely ZZ (:trac:13014)::

sage: bool(gcd(2/5, 3/7) == gcd(SR(2/5), SR(3/7)))
True

Make sure that the gcd of Expressions stays symbolic::

sage: parent(gcd(2, 4))
Integer Ring
sage: parent(gcd(SR(2), 4))
Symbolic Ring
sage: parent(gcd(2, SR(4)))
Symbolic Ring
sage: parent(gcd(SR(2), SR(4)))
Symbolic Ring

Verify that objects without gcd methods but which can't be
coerced to ZZ or QQ raise an error::

sage: F.<a,b> = FreeMonoid(2)
sage: gcd(a,b)
Traceback (most recent call last):
...
TypeError: unable to find gcd

"""
# Most common use case first:
if b is not None:
try:
return a.gcd(b, **kwargs)
except (AttributeError, TypeError):
pass
try:
return ZZ(a).gcd(ZZ(b))
except TypeError:
raise TypeError("unable to find gcd")

from sage.structure.sequence import Sequence
seq = Sequence(a)
U = seq.universe()
if U is ZZ or U in integer_types:  # ZZ.has_coerce_map_from(U):
return GCD_list(a)
return __GCD_sequence(seq, **kwargs)
File:      ~/sage/local/lib/python2.7/site-packages/sage/arith/misc.py
Type:      function