Short explanation of Python

At the unix prompt, type "python" (and hit return) and you'll get the
python prompt:
>>>
To _stop_ python and return to the unix prompt, type "Control-D" at
the python prompt.
If python gets stuck in a loop or in a too-long process, "Control-C"
interrupts it and returns you to the prompt.
In its simplest use, the python prompt gives a read-evaluate-print
loop, which has many built-in functions useful for basic computational
number theory. Addition is +, multiplication is *, division is /,
substraction is -, use of parentheses is as usual. A slightly less
standard use is ** for exponentiation, so, for example, 2**5=32. The
python prompt's loop can be used as a simple calculator, by entering
an expression and hitting "return" to evaluate it:
>>> 2*3
6
>>> 4 * 4
16
>>> 2**10
1024
>>> (3+5) * (1+2)
24
>>>
Whitespace between operators doesn't matter.
An unusual feature of python is that it has built-in
infinite-precision integers, of arbitrary size. These are denoted by
appending an "L" to the numeral. If the numbers get too large for
ordinary integers, you'll get an overflow error:
>>> 2 ** 100
Traceback (innermost last):
File "", line 1, in ?
OverflowError: integer pow()
>>>
But if you use "long" integers it'll be fine:
>>> 2L ** 100
1267650600228229401496703205376L
>>>
Of course, you can still ask the machine to do tedious and stupid
things, such as
>>> 2L ** 1000000
## If you do this, for example, the machine will appear to hang. If
## you realize that you've made a stupid request, you _can_ stop it
## in the middle without harming anything: do Control-C, and you'll
## be returned to the prompt.
For use in crypto and other computational number theory, there is a
built-in function which does _modular_exponentiation_: to compute
x^e % m (x to the e power reduced modulo m)
do _not_ do
>>> (x**e) % m ## bad!
but instead do
>>> pow(x,e,m) ## good
The latter uses a smart algorithm. So, for example, ridiculously large
exponents are ok (as long as the "L" suffix is used):
>>> pow(2L, 10L**100+1, 10L**100+1)
6660888126245688699182136543775795641628347778449324704651411345556300289268422357122875536174966145L
takes an imperceptible amount of time to evaluate. Very good.
#################################################################
#################################################################
There are built-in mathematical functions, too, but preparation for
them requires _importing_ the "math module": do
>>> import math
just once at the beginning of a python session, to import the math
module. Thereafter, the following functions and constants (among
others) are available:
math.log10( ) ## log base 10
math.pi ## 3.14159265359
math.sqrt( ) ## square root, in floating-point: watch out!
math.acos( ) ## inverse cosine
math.sin( ) ## sine function, in radians
math.atan2(,) ## = arctan( firstargument / secondargument )
math.exp( ) ## exponentiation base e
math.asin( ) ## arcsine
math.floor( ) ## greatest integer less-than-or-equal-to: the floor function
math.fabs( ) ## least integer greater-than-or-equal-to: the ceiling function
math.log( ) ## natural log
math.e ## 2.71828182846
math.atan( ) ## arctangent
The usage as set up here requires the prefix "math", as in
>>> math.log10(2)
0.301029995664
>>>
On hazard is that these functions only keep a fixed number of decimal
places of "precision", so
######################################################################
To _replay_ and _edit_ the last command, a nice subset of EMACS
text-editing capabilities is available: among other things, a basic
set of commands is
("C-x" is an abbreviation for "Control-x")
("M-x" is an abbreviation for "Meta-x")
C-f ;; move forward by one character
C-b ;; move backward by one character
M-f ;; move forward by one word
M-b ;; move backward by one word
C-p ;; recall previous command (can be iterated further!)
C-n ;; move to next command
C-a ;; move to beginning of line
C-e ;; move to end of line
C-d ;; delete next character
M-d ;; delete next word
DEL ;; delete previous character
M-DEL ;; delete previous word
C-k ;; delete from point to end of line
The arrow keys usually work, also.
######################################################################
A related organizational tool (as well as actualy programming
capability) is the possibility of _named_variables_. This can be done
at the python command line loop, using "=" to assign values to
variables.
>>> n = 1001
>>> n
1001
>>> n = n+1
>>> n
1002
>>>
This allows more coherent treatment of complicated expressions:
>>> n =1001
>>> n
1001
>>> n = n+1
>>> n
1002
>>> n = 1000001L
>>> n
1000001L
>>> a = pow(2,n,n)
>>> a
210991L
>>>
######################################################################
"While loops" are easy to write:
>>> i=1
>>> while i<10: ## hit return at end of line
... print `i` ## hit tab at beginning of line, return at end
... i = i+1 ## hit tab at beginning of line, return at end
... ## hit return to close up the block
1
2
3
4
5
6
7
8
9
>>>
Note that the backquotes convert _numbers_ to _strings_
Note that braces are _not_ used. Rather, code blocks are indicated by
_indentation_. Thus, every line in the "while block" must be indented,
conventionally by a tab. Sub-blocks have their own further
indentation:
>>> i = 1 ## hit return
>>> j = 1 ## hit return
>>> while i<5: ## hit return
... while j <= i: ## tab at beginning, return at end of line
... print `i+j` ## _two_ tabs at beginning, return at end
... j = j+1 ## _two_ tabs at beginning, return at end
... i = i+1 ## _one_ tab at beginning, return at end
... ## just a return, to close the outer block
2
4
6
8
>>>
######################################################################
"For loops" are similar, and also "if/else" statements are reasonable:
>>> n = 1000001
>>> n % 3
2
>>> n = 1000001
>>> for i in range(1,1001):
... if n % i == 0:
... print `i`
...
1
101
>>>
The syntax of the "else" clause is:
Note that the _test_ for equality (as opposed to _assignment_ of
variable values) is a _double_ equal sign.
The "range" thingy tells the variable i to assume all integer values
including the bottom but excluding the top value. It has an optional
argument that tells how much to increment it (the default is 1):
>>> for i in range(1,10,3):
... print `i`
...
1
4
7
>>>
If the range is rather large, it may be more economical to use a
variant construct "xrange", rather than plain "range", which does not
create the whole list in memory at one time:
>>> for i in xrange(1,100000):
... if i== 12345:
... print `i`
... elif i== 1234501:
... print "Hello"
... else:
... pass
12345
'Hello'
>>>
This example also showed how to print a string. It also showed how to
have a "no-operation" occur: the keyword is "pass"
######################################################################
It is easy to define simple functions to use in the python
command-line loop, using "def" and "return" keywords:
>>> def f(x): ## hit return
... return x*x*x-3*x*x+17*x-1 ## hit tab at beginning of line, return at end
... ## hit return to end definition block
>>> f(1)
14
>>> f(0)
-1
>>> f(-1)
-22
>>> f(2)
29
>>>
Somewhat more complicated things can also be set up in code blocks,
using "if/else" blocks and "for" or "while" loops:
>>> def f(n):
... if n == 1:
... return 1
... elif n==2:
... return 2
... else:
... return 3
...
>>> f(4)
3
>>>
Variable names and function names can be long and descriptive if you
want:
>>> def primality_test(n):
... bound = int( math.sqrt(n) )
... for i in range(3,bound+1,2):
... if n % i == 0:
... return `i` + " divides " + `n`
... return `n` + " is prime "
...
>>> primality_test(101)
'101 is prime '
>>> primality_test(105)
'3 divides 105'
>>>
Note that the "+" operator also concatenates _strings_, which can be
delimited by double-quotes.
######################################################################
_List_ syntax is reasonable:
>>> mylist = [1,2,3]
>>> mylist
[1, 2, 3]
>>> mylist.append(101)
>>> mylist
[1, 2, 3, 101]
>>> mylist.append(123)
>>> mylist
[1, 2, 3, 101, 123]
>>> mylist
Lists can be used in _for_loops_:
>>> for i in mylist:
... print `i`
...
1
2
3
101
123
>>>
Here's the time to point out a variant form of _print_, which doesn't
insert a newline after each item, but only a space:
>>> for i in mylist:
... print `i`,
...
1 2 3 101 123
>>>
That is, the comma after the `i` causes the "print" to only insert a
space rather than newline.
The length of a list is accessible by the "len" function, which also
can compute the length of a _string_:
>>> len(mylist)
5
>>> len("hello")
5
>>>
The various elements of a list are accessible by typical index
notation, with indices beginning at 0:
>>> mylist[2]
3
>>> mylist[0]
1
>>>
_Slices_ of lists use a funny but reasonable notation
>>> mylist[0:3]
[1, 2, 3]
>>> mylist[:-1]
[1, 2, 3, 101]
>>> mylist[:-2]
[1, 2, 3]
>>> mylist[0:-2]
[1, 2, 3]
>>> mylist[1:-2]
[2, 3]
>>> mylist[2:-2]
[3]
>>> mylist[3:-2]
[]
>>> myslice = mylist[3:]
>>> myslice
[101, 123]
>>>
######################################################################
When you get tired of retyping at the command-line loop, you can (of
course) put python code into files and _either_ "run" such files on
their own, _or_ use them as "modules" from the python command-line
loop itself.
To load into the command loop files defining
functions/subroutines/methods, these files should end with ".py", like
"myfile.py", _and_ should either be in your current directory (in a
unix sense), or in your python module search path. (At the unix prompt
do "echo $PYTHONPATH" to see the value of this environmental
variable.)
Suppose that myfile.py contains just the two lines (ended by a newline!)
def f(n):
return n+1
(Assuming that the python interpreter can find the files, because
they're in the search path), to load myfile.py into the python loop,
do
>>> import myfile
Note that the suffix is not included. Then functions defined in myfile
can be called by
>>> myfile.f(5)
6
If the definition of myfile.f is changed in myfile.py and you want to
"reload", the syntax is
>>> reload(myfile)
To load functions/methods in a manner so that the prefix "myfile." is
not needed, use the syntax
>>> from myfile import f
>>> f(11)
12
>>>
Such Python modules can include auxiliary functions called
internally. Such internal use does not require use of the prefix
naming the module. For example, myfile.py might contain the 3 lines
(with newline at the end)
import math
def mysqrt(n):
return math.sqrt(n)
Then
>>> reload(myfile)
>>> myfile.mysqrt(16)
4.0
>>>