|
 |
CS 3723
Programming Languages |
1. Python Introduction
|
|
Reference links given below will be to the online book:
Building skills in Python
1.1. Simple Loops and Conditionals,
Output, Formatting:
Fibonacci Numbers:
Here are two versions of a sample Python program that prints
successive Fibonacci numbers, five to a line.
Below are equivalent C and Ruby programs.
Fibonacci Number
Example |
Python Version |
Using print "from
the future" |
# fib.py: standard version
import sys
f0, f1, i, last = \
0, 1, 0, 30
while i < last:
f2 = f0 + f1
sys.stdout.write("%i\t " % f0)
f0, f1 = f1, f2
i += 1
if i%5 == 0:
sys.stdout.write("\n")
sys.stdout.write("\n")
|
# fib2.py: uses print function
from __future__ import print_function
f0, f1, i, last = 0, 1, 0, 30
while i < last:
f2 = f0 + f1
print("%i\t " % f0, end='')
f0, f1 = f1, f2
i += 1
if i%5 == 0:
print() # prints newline
print() # prints newline
|
C Version |
Ruby Version |
// fib.c: same program
#include <stdio.h>
int main() {
int F0 = 0, F1 = 1, F2,
i = 0, last = 30;
while (i < last) {
F2 = F0 + F1;
printf("%i\t",F0);
F0 = F1; F1 = F2;
i++;
if (i%5 == 0)
printf("\n");
}
printf("\n");
}
|
# ruby.rb: Ruby version
f0, f1, i, last =
0, 1, 0, 30
while i < last
f2 = f0 + f1
printf "%i\t", f0
f0, f1 = f1, f2
i += 1
if i%5 == 0
printf "\n"
end
end
printf "\n"
|
Common
Output |
% python fib.py -tt
0 1 1 2 3
5 8 13 21 34
55 89 144 233 377
610 987 1597 2584 4181
6765 10946 17711 28657 46368
75025 121393 196418 317811 514229 |
Items of Interest or for study:
- Blocks of statements are given by indentation, preceded by
a ":". See
Python Syntax Rules and
Syntax Formalities.
The portion indented is called a Suite, and the sequence of
blanks and tabs on each line of indentation must be exactly the
same. It is suggested that you use 4 spaces for each level of
indentation, and no tabs. (I was able to set up my editor so that
a tab key gave me 4 spaces and no tabs.) Notice that the if
inside the while has a second level of indentation.
My favorite syntax error is to leave off the ":" before the suite.
- Python has a
Multiple Assignment Statement, like Ruby, but unlike C.
- In some cases Python lets you continue a statement onto the
next line (and not worry about indenting on that next line).
Any time you're inside parens or brackets you can continue.
Otherwise you can always continue with a "\" at the end.
(I show this above. Here there was no need, since the line
isn't very long, but this method does nicely show the pairing
of variable with value assigned.)
- Single statements can always have a semi-colon at the end,
but it's not required, so Python seldom uses it. This lets you
put more than one statement on a line, but this should usually
(or always) be avoided.
- Python has if-elif-else, for,
and while statements. See
Truth, Comparison and Conditional Processing,
and
Loops and Iterative Processing.
- As an amazing addition for range checking, Python allows:
if 0 < x < 8, in place of
if 0 < x and x < 8, which in Python is equivalent and also legal.
This common beginner error is legal in Python and can be extended
to a longer list of conditions.
- Printing:
Python 2.x has a print statement. Normally it prints a newline
at the end.
You can use print with a trailing comma, in which case it
prints a final blank. Since it seems that print always puts either
a newline or a blank at the end, print in Python 2.x is
not useful for general-purpose work.
In Python 3.x this has become a print() function with a
number of different features. In particular you can write
print(a, b, end='') to print nothing at the end.
Something that works for both Python 2 and 3 is to add import sys
and use the function sys.stdout.write() which expects its argument
to be a single string, and writes it out (without adding a newline or a
blank at the end). So I plan to mostly use this.
Alternatively, you can use Python 2, but still import the
print function "from the future", as shown in the
middle program above. (A science fiction concept.)
- For the weird stuff inside the parens after write above
that looks the same as a C format, see
The String Formatting Operation, %, which is about a quarter of
the way down the page:
Strings. As an operator in this context, % takes a
format string to its left, and uses it to process one
operand to its right to yield a string.
1.2. Functions, Library and User-defined:
Calculating π to 16 digits:
Calculating Pi Using a Square
Root Formula |
Python Version |
C Version |
# pi.py: Pi using sqrt
import sys
import math
def pi(n):
p = 2 # final product
b = 0 # each denominator
for i in range(n):
b = math.sqrt(2 + b)
t = 2/b # term
p *= t
if i%2 == 0:
sys.stdout.write(" i: " +
("%2i" % i) + ", t: " +
("%.16f" % t) + ", p: " +
("%.16f" % p) + "\n")
return p
sys.stdout.write("pi: " +
("%.16f" % pi(25)) + "\n")
|
// fib.c: same program
#include <stdio.h>
#include <math.h>
double pi(int n) {
double p = 2; // final product
double b = 0; // each denominator
double t;
int i;
for (i=0; i < n; i++) {
b = sqrt(2 + b);
t = 2/b; // term
p *= t;
if (i%2 == 0) {
printf(" i: %2i, t: %.16f",
i, t);
printf(", p: %.16f\n", p);
}
}
return p;
}
int main() {
printf("pi: %.16f\n", pi(25));
}
|
Common
Output |
% python pi.py -tt
i: 0, t: 1.4142135623730949, p: 2.8284271247461898
i: 2, t: 1.0195911582083184, p: 3.1214451522580524
i: 4, t: 1.0012059964703925, p: 3.1403311569547530
i: 6, t: 1.0000753038310954, p: 3.1415138011443009
i: 8, t: 1.0000047062125721, p: 3.1415877252771600
i: 10, t: 1.0000002941372044, p: 3.1415923455701180
i: 12, t: 1.0000000183835711, p: 3.1415926343385636
i: 14, t: 1.0000000011489731, p: 3.1415926523865920
i: 16, t: 1.0000000000718108, p: 3.1415926535145942
i: 18, t: 1.0000000000044882, p: 3.1415926535850947
i: 20, t: 1.0000000000002804, p: 3.1415926535895005
i: 22, t: 1.0000000000000175, p: 3.1415926535897758
i: 24, t: 1.0000000000000011, p: 3.1415926535897931
pi: 3.1415926535897931
|
The above code calculates
pi using 25 terms of the following infinite product
(which must be solved for pi):
Here we as mainly interested in language details rather than
in the algorithm to calculate the product.
Items of Interest or for study:
- Library Functions:
The sqrt function is an example of a library function.
It comes from Python's
math library, which is "imported".
- User-defined Functions:
This example shows a function definition: pi.
[See
Functions for a long discussion of functions in Python,
more than you want to know.] Here are some items of interest:
- A function definition starts with the reserved word
def.
- Don't forget the ":" before the indented suite which
is the function body.
- You must have parens after the name of the function in
the first line of the definition, and parens after a call to the function.
Inside the parens are formal parameters (in the definition)
and actual parameters (in the function call).
If there are no parameters, you still need empty parens.
- Python does not (and cannot) specify a return type.
You can always return anything you want, or not do a return (and
even mix this up: sometimes returning and sometimes not).
A return uses the reserved word return. When a return
is encountered, that terminates the function.
- If your function doesn't return anything, Python
will still return None.
- Output Formatting:
This example shows more of the weird output formatting that
was in the previous example, using the operator "%".
- The parens in "("%2i" % i)" above are not required.
Notice that we can only continue that write statement along 3
extra lines because the breaks to a new line occur inside parens.
- The output formatting could be done all at once, as with:
sys.stdout.write(" i: %2i, t: %.16f, p: %.16f\n" % (i, t, p))
Notice that there is an initial formatting string inside double
quotes, followed by the formatting operator "%", and then by
the tuple "(i, t, p)" giving the three
variables to be formatted.
1.3. Scope of Variables Inside Functions:
In the function defined above, notice the lack of declarations:
not for the function's return type (or whether it returns nothing),
not for the types of the parameters. No types declared for local variables,
and indeed no types declared for any variables.
By default, any variables used inside a function have local scope
(are known only inside the function) in case they are given
a value inside the function. If they are not given a value inside
the function, they have global scope by default.
A variable given a value can be made global by declaring it
"global". Parameters also have local scope.
The small program at the right illustrates these issues.
Notice that there are two separate b variables in this code,
one inside the function and one outside, but there is only
one a variable. The statement commented out inside the
function causes an error: "UnboundLocalError:
local variable 'c' referenced before assignment". |
Scope of Variables Inside Functions |
Output |
#!/usr/bin/python -tt
import sys
a = 42
b = 37
c = 28
def foo():
global a
a = 13
b = -96
# c += 1
foo()
sys.stdout.write(str(a)+
" " + str(b) + "\n")
| % ./foo.py
13 37 |
|
1.4. Arbitrarily Large Integer Arithmetic
in Python:
An amazing calculation of arbitrarily
many digits of π:
The algorithm used is too complicated to explain in this course
(but see the end of this section).
We're mainly interested in the programming aspects.
Digits of Pi
(forever) |
# pi_inf.py: digits of pi forever
import sys
k, a, b, a1, b1 = 2, 4, 1, 12, 4
while True: # or num != 0, or non-empty str
p, q, k = k*k, 2*k+1, k+1
a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
d, d1 = a/b, a1/b1
while d == d1:
sys.stdout.write(str(d))
a, a1 = 10*(a%b), 10*(a1%b1)
d, d1 = a/b, a1/b1
| # pi_inf2.py: digits of pi forever
from __future__ import print_function
k, a, b, a1, b1 = \
2, 4, 1, 12, 4
while True:
p, q, k = \
k*k, 2*k+1, k+1
a, b, a1, b1 = \
a1, b1, p*a+q*a1, p*b+q*b1
d, d1 = \
a/b, a1/b1
while d == d1:
print(d, end='')
a, a1 = \
10*(a%b), 10*(a1%b1)
d, d1 = \
a/b, a1/b1
|
Output |
% python pi_inf.py -tt
31415926535897932384626433832795028841971693993751058209749445923078164 ...
File "pi.inf.py", line 11, in
a, a1 = 10*(a%b), 10*(a1%b1)
KeyboardInterrupt
|
Of course the program won't print digits of pi "forever".
For one thing, the program requires ever increasing amounts of
memory, so on a real machine it would have to run out.
This program and one below only "work" because Python supports
arbitrarily large integers and operations on them. (Again,
the maximum size depends on the amount of memory available,
but there are other limitations, such as special tables
or constants.)
The next program constrains the output and prints it in
a more orderly fashion, with periodic extra blanks and newlines:
|