[sf-lug] [PyClass] the print token keyword statement function builtin magic
jim
jim at well.com
Fri Sep 26 12:44:51 PDT 2008
At our first python lesson with asheesh at the grind, there
was a question about the print print() function that in
release 3.0 replaces the print statement that's used in
previous releases of Python.
The reference for the entire Python language is here:
http://docs.python.org/ref/
Links specific to the print statement/function issue:
http://www.python.org/dev/peps/pep-3105/
# "Make a print function" PEP : Guido's rationale for the change
http://mail.python.org/pipermail/python-dev/2005-September/056154.html
# some of guido's arguments in favor of the change
http://www.comp.leeds.ac.uk/nde/papers/teachpy3.html
# see 2.4 and following re asymmetric console I/O.
http://www.python.org/download/releases/3.0/
# release page for python 3.0 (see the what's new link)
http://www.win.tue.nl/~wstomv/edu/python/python-observations.html
# Tom Verhoeff's personal assessment of Python 2.2.2 design points
about PEPs and Python:
http://www.python.org/dev/peps/
# TOC of PEPs, categorized
http://www.python.org/dev/peps/pep-0001/
# PEP #1: "What is a PEP", a PEP about PEPs
My comments per discussion and terms in the lesson:
programs are made of source code that we type, and typically
consist of a set of one or more (usually lots more) "statements".
older programming languages have a character that is used to
end a statement. python does not have such a statement terminating
character.
thinking like a computer scientist, it seems to me, includes
knowing that there's an interpreter or compiler that is reading
our code. formally, interpreters and compilers are built as rules
engines, aka state machines. they begin in a neutral state and
start reading our code, breaking our code down into a stream of
tokens.
as part of evaluating each token, they change their state,
usually reducing the number of legal possibilities for the
subsequent token. at some point there's no further reduction or
other adjustment, which means they're done reading the token
stream.
the statement terminating character tells the interpreter or
compiler that the programmer intends that the interpreter or
compiler return to a neutral state so's to be ready to work on
the next stream of tokens (i.e. "statement"). if the programmer
puts the statement terminating character in the wrong place,
the interpreter or compiler generates an error and quits.
in python, statements are delimited by newlines. to write a
long statement, you use the \ (backslash) character as the last
character on the line and continue writing your statement on
the line below. the python interpreter will ignore the newline
that immediately follows the \ character and continue
interpreting the token stream as part of the same statement.
it strikes me as unfortunately muddying that the word
statement is used in the discussion of python keywords.
http://docs.python.org/ref/keywords.html
programming languages can be thought of as consisting of a
set of keywords (such as "if", "while", "def", "import", the
now notorious "print", and so on) along with a set of operators
(such as +, -, (), =, ==, !=, >, and so on) and also including
a set of syntax rules that tells the programmer how to use the
keywords and operators and the all-important identifiers that
the programmer makes up as names of variables, functions,
classes, and objects.
the term "expression" often pops up in discussions along
these lines. i think a useful definition of "expression" is
"a combination of one or more operands with zero or more
operators". mathematicians would probably disagree, but the
definition is useful nonetheless.
the idea of an expression is that the interpreter or
compiler resolves the expression to a single value. thus the
expression 1 + 1 is resolved to the single token value of 2.
the expression 4 * 5 + 2 * 3 is similarly resolved to a
single value, but only by following the proper syntax rules.
beginners looking at 4 * 5 + 2 * 3 might multiply 4 * 5 to
get 20 and then add 2 to get 22 and then multiply by 3 to get
66. the syntax rules force multiplication first, which means
multiplying 4 * 5 to get 20 and then multiplying 2 * 3 to get
6 and then adding 20 with 6. knowing the syntax rules means
knowing the rules of operator precedence, among other things
(knowing that multiplication is done before addition).
it's helpful to think of 4 * 5 + 2 * 3 as a complex
expression made of sub-expressions: 4 * 5 is one
sub-expression and 2 * 3 is another sub-expression.
evaluate 4 * 5 first to get 20. then evaluate 2 * 3 to
get 6. now we've resolved our two sub-expressions to single
values 20 and 6. as there are no other sub-expressions to
work on, we have reduced our original to 20 + 6, a simple
expression that we can resolve to a single value 26.
it's helpful to group sub-expressions with the ()
(parentheses) characters. so we could rewrite the original
expression as (4 * 5) + (2 * 3) to make things clearer.
be careful, as the rules of precedence govern the use
of the () characters, too. if we write 4 * (5 + 2) * 3,
the rules of precedence force resolution of things in
parentheses absolutely first: so 5 + 2 is resolved to a
single value of 7, to produce 4 * 7 * 3. because the only
operators are multiplication, precedence doesn't have an
effect (and the interpreter or compiler resolves from
left to right in this case), so 4 * 7 becomes 28 and
28 * 3 becomes the single value of 84.
we can think of the following as an expression:
x = 4 * 5 + 2 * 3
how many operands are there above? x, 4, 5, 3, and 2,
five operands. how many operators? =, *, +, and *, four
operators. which operator has the highest precedence?
the * operator. which operator is next? the + operator.
which is last? the = operator.
so resolving the expression can be notated as follows:
x = ((4 * 5) + (2 * 3))
x = ((20) + (6))
x = (26)
each of the above, written as is, is not only an
expression but a statement in python. notice that there
are no keywords (no "global", "pass", "except", "else",
and so on) in the above statements.
the concept of a "function" needs some unwraveling.
some older programming languages distinguish between a
"function: and a "procedure". in this mindframe, you can
think of a function as being a procedure that returns a
single value (and a procedure as doing something without
returning any value).
in python, the word "function" covers both cases (the
word "procedure" isn't needed, a function doesn't have
to return a value).
http://www.penzilla.net/tutorials/python/functions/
programmers create functions by using the "def" keyword.
def doit():
x = ((4 * 5) + (2 * 3))
print x
return x
print "hi"
the "def" keyword is followed by the name of the
function, in this case "doit". but the programmer must
follow the function name with the () characters. the
result tells the python interpreter that this is a
function name and the code that defines it will be
indented in a block following the : character.
the block of code for the doit() function is indented.
note that indenting is vital. the final
print "hi"
statement is not part of the doit() function definition.
the function definition begins with a statement that
assigns 26 to the variable x, then a print x statement,
then a return x statement.
to use the doit() function we name it somewhere in
our program.
doit()
the above is a function call that is a statement that
tells the python interpreter to run the code that
defines the doit() function.
as the program runs, 26 is displayed on the console.
below is a complete python program (also file is attached)
# doing.py 20080926 jim at well.com ---------------
# function definitions on top so they're globally available
def doit():
# this is how to create a function
x = ((4 * 5) + (2 * 3))
print "From the doit() function: x = ", x
return x
# using print statements throughout the program let you
# see the program flow--if any error messages occur, the
# previous and following print statements let you identify
# the part of your code that's suspect.
print "\n\nstarting to run\n"
# this calls the previously defined doit() function
doit()
# the first use of the doit() function ignored the value
# that doit() returned. this next use shows how to capture
# a function's return value and use it.
print "\n\nadding a feature"
y = doit()
print "\ncaptured doit's return as y and adding one: ", (y + 1)
print "\n\nend of program\n\n\n\n"
# ---------------End Of Program---------------
Here's the same program with a bug. run it just as it is.
notice the error message. see the carot character pointing
up to the end of the word print. can you find the error in
the code? (file is attached)
# doingwrong.py 20080926 jim at well.com ---------------
# function definitions on top so they're globally available
def doit():
# this is how to create a function
x = ((4 * 5) + (2 * 3)
print "From the doit() function: x = ", x
return x
# using print statements throughout the program let you
# see the program flow--if any error messages occur, the
# previous and following print statements let you identify
# the part of your code that's suspect.
print "\n\nstarting to run\n"
# this calls the previously defined doit() function
doit()
# the first use of the doit() function ignored the value
# that doit() returned. this next use shows how to capture
# a function's return value and use it.
print "\n\nadding a feature"
y = doit()
print "\ncaptured doit's return as y and adding one: ", (y + 1)
print "\n\nend of program\n\n\n\n"
# ---------------End Of Program---------------
in the two (very similar) programs above, the lines
doit()
and
y = doit()
are both statements.
likewise, any of the lines with the print keyword, such as
print "\n\n starting to run\n"
are also statements. it's helpful to distinguish between
the keywords of a language and the concept of a statement
as the language's rules of notation dictate.
the lesson uses various terms that seem not fully explained.
you'll probably look things up. the following two terms ought
to help a bit.
Builtin and magic:
the python interpreter is constructed to read python code,
compare the code to its keywords, operators, and rules of
syntax, and also let you use some functions that are not
keywords or operators but are built in as part of the python
interpreter.
http://docs.python.org/lib/built-in-funcs.html
in release 3.0, the interpreter will not implement a
print keyword but rather provide a print() function as one
of its builtins.
Magic is technology we don't understand (or don't yet
understand, there are variations of the thought). the word
"magic" in Python has a particular meaning: identifiers with
double underscores.
the term "identifier" means some name that some programmer
makes up. in the above example programs, x and y are both
identifiers, and doit is an identifier, too. you make up
names for variables, functions, and classes: those are
identifiers. when you use programs written by other
programmers (which are in libraries and other modules),
those programs have identifiers, too.
one of the biggest issues of python is that of name
spaces. the idea is that if you have separate name spaces,
then you can use the same identifier in each of the name
spaces without confusing the python interpreter.
the following link is a particularly good intro to some
python features (IBM has some excellent information on Python)
that shows a few "magic" identifiers (such as __name__ and
a couple of others):
http://www-128.ibm.com/developerworks/library/l-cheatsheet3.html
the following link shows an email thread between two
"pythonistas" discussing issues of magic.
http://mail.python.org/pipermail/python-list/2007-June/444043.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: doing.py
Type: text/x-python
Size: 920 bytes
Desc: not available
URL: <http://linuxmafia.com/pipermail/sf-lug/attachments/20080926/9dba65b4/attachment.py>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: doingwrong.py
Type: text/x-python
Size: 924 bytes
Desc: not available
URL: <http://linuxmafia.com/pipermail/sf-lug/attachments/20080926/9dba65b4/attachment-0001.py>
More information about the sf-lug
mailing list