# 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