This chapter describes Jython’s syntax and statements. Jython has a simple, clean syntax that produces easy-to-read code, often considered the antithesis to the intricate appearances of Java, C, or Perl. Before addressing syntax, this chapter introduces Jython’s interactive mode. This mode allows you to enter code one line at a time like common shell consoles, and it is the perfect venue for exploring Jython’s syntax.
Programming is often a succession of little puzzles. These little puzzles need to be worked out, tested, and confirmed before they can be added to the larger whole. That’s where the interactive console comes in—you can explore code interactively, test things immediately, and experiment until the little puzzles are solved. The use of the interactive console, also called the interactive interpreter, is similar to shell programming, where you can enter commands interactively until they work, then place them in a file to make a shell script. The similarity fades when you realize that Jython itself is a very full and rich object-oriented programming language with a clean, easy-to-understand syntax.
The interactive console is started by running jython
without any parameters or by adding the -i
command-line switch. After starting Jython you should see something that looks similar to this:
Jython 2.0 on java1.2.2 (JIT: symcjit) Type "copyright", "credits" or "license" for more information. >>>_
The first line printed after starting Jython should include version information about Jython and Java as well as information about the JIT you are using. If you set the JAVA_COMPILER
environment variable to NONE
, Jython would confirm the change in JIT:
Jython 2.0 on java1.2.2 (JIT: NONE) Type "copyright", "credits" or "license" for more information. >>>
The >
>
>
in the third line is the prompt for the interactive interpreter. At this prompt you can type Jython code that is evaluated as each line is entered. There is also a second prompt, which is three periods, .... This is used when statements span multiple physical lines.
This testing, experimentation, and discovery within interactive mode is not limited to Jython. The interactive console is a powerful way of experimenting with and testing Java code. For this book, interactive mode is the primary means of learning Jython. Examples in the first part of this book are designed to be easy to experiment with, examine, and explore in interactive mode. The prompt symbols, >
>
>
and .
.
.
, are used to designate the use of the interactive interpreter throughout this book.
Simple Jython statements are contained in a logical line. What is a logical line? you might ask. Java and many other languages make this clear with punctuation. The semicolon is a line-separator in Java. A simple Java print
would be
System.out.println("Hello world");
Notice the semicolon. Now look at the comparable simple Jython print
statement:
print "Hello world"
There are no semicolons to mark the end of the logical line. The semicolon has been a standard for terminating lines in many languages, but in Jython, a newline is sufficient to denote the boundary between logical lines—with but a few exceptions. If a Jython print
statement were entered into the interactive interpreter, pressing the Enter key would cause the interpreter to execute the contents of that logical line. The same goes for a Jython file. Separate lines of Jython code in a file are interpreted as separate logical lines, unless they fit one of the exceptions that follow.
There are cases in which the logical line for simple statements is not the same as the physical line. These cases are as follows:
Semicolon
Backslash
Open groupings
Triple-quotes
The first case is the semicolon. This is the only case concerned with shortening the logical line. To place two or more logical lines on the same physical line, use the semicolon to separate statements. Even if there are not multiple statements on one line, the semicolon doesn’t hurt anything. So, if Java programming habits lead to stray semicolons at the end of statements, no harm is done. Remember to be aware of code clarity when choosing this syntax to ensure that readability is not sacrificed for the sake of compactness.
Listing 1.1 has multiple print
statements on one physical line. The semicolon acts as the logical-line separator between these two print statements. The second statement, however, does not have a semicolon, because the newline character after it functions as the separator.
Example 1.1. Use of the Semicolon
>>># it's tradition, what can I say >>>print "Hello "; print "world" Hello world
Notice that the print statement automatically inserted a newline. This is part of the behavior of Jython’s print
statement. If this is not desired, you can append a comma after the print
statement which pre-pends a space to the second print
statement instead:
>>>print "hello ",; print "world" hello world
The backslash () character is a line-continuation character. Multiple lines can be used to form one logical line with the
. An assignment is a simple Jython statement that binds a value to a variable, but what if you need to add so many values that they extended beyond the physical line? Listing 1.2 shows how the
can be used to join multiple lines to do this. Listing 1.2 does not work interactively despite the legal syntax. To test Listing 1.2, place the code in a file (
backslash.py
used in example) and run it at the command line with jython
backslash.
py
.
Example 1.2. Line Continuations with the Backslash
# file: backslash.py var = 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 print var
Results from running jython backslash.py
at the command prompt:
55
Open groupings—meaning paired brackets []
, braces {}
, and parentheses ()
— have their open (left) character on one line, and the closing character on a subsequent line. The logical line is extended until the closing half of these groupings appears. Listing 1.3 uses open groupings to spread a print statement over multiple physical lines. Listing 1.3 also does not work interactively despite being legal syntax (as of version 2.1a1).
Example 1.3. Using Parentheses to Span Multiple Lines
# file: parens.py print ("this, " + "that, " + "the other thing.")
Results from running jython parens.py
:
this, that, the other thing
The indentations on the second and third lines of listing 1.3 are for appearances—this is unrelated to the continuation of the logical line. Indention matters in Jython, but in the case of joining lines with or open enclosures, the indentation of the continued lines do not matter. It’s the indentation of the first line that does. Indention rules are addressed with compound statements later.
Triple-Quotes
In Jython, you have the option to use three matching quotes to mark the start and end of a string, matching either """
or '''
. In a triple-quoted string, newlines and contained quotes are all preserved except for another triple-quote. Listing 1.4 shows a triple-quoted string spanning multiple lines. Note how it preserves internal quotes plus newline characters. Listing 1.4 is legal syntax, but also does not work interactively.
Example 1.4. Triple-Quoted Strings
# file: triplequote.py print """This is a triple-quoted string. Newlines and quotation marks such as " and ' are preserved in the string."""
Results from running jython triplequote.py
:
This is a triple-quoted string. Newlines and quotation marks such as " and ' are preserved in the string.
With newline characters acting as the logical-line separators, it should be obvious that Jython already has much less punctuation than Java. What further reduces line noise is Jython’s notation of code blocks in compound statements. These groupings, or “blocks” of code, are designated in Java by their enclosure in braces {}
.
Here lies an important distinction—Jython does not use braces to group statements but rather uses a combination of the :
character and indention whitespace. Java’s braces handle multiple levels of groupings with multiple enclosures of braces, or braces within braces { {} }
. Jython instead uses multiple levels of indention—one indention for first grouping, two indentions for the second, and so on. Listing 1.5 uses Jython’s if
statement to show how compound statements use the :
and indention to denote groupings of code.
Example 1.5. Indention-Based Groupings
>>>if 1: ... print "Outer" ... if 1: ... print "Inner" ... print "Outer- again" ... Outer Inner Outer- again
Notice how the execution of the compound statement happens only after the newline is entered at the leftmost margin in line six. This entry at the leftmost level notifies the interpreter that the indented grouping is completed and thus, the compound statement is completed.
Looking back at Listing 1.1 from earlier in this chapter, we see another important feature.The #
sign. This designates a comment. All code between the #
sign and the end of the physical line is ignored by the interpreter. Its appearance is not restricted to the beginning of a line; it can appear after a statement like this:
print "Hello world" # It's tradition, what can I do
The newline still terminates the logical line, but the space between #
and the newline is treated as a comment and is ignored by the interpreter.
Another way to comment code is with anonymous string literals. If you do not assign a string to a variable, it is anonymous, and does not affect the namespace in which it appears. This makes strings useful as comments, especially triple-quoted strings because they allow comments to span multiple lines. Listing 1.6 shows different comments. Listing 1.6 does not currently work in the interactive interpreter as noted earlier.
Example 1.6. Comments
# file: comments.py # This is a comment "This works for a comment" """This comment can span multiple lines. Code that you do not want executed can go in triple quotes, and it is safe to use other quotation marks within the triple quotes, such as: print "hello" """
There is no output from running jython
comments.py
.
The exploration and discovery mentioned when introducing interactive mode depends on introspection, the ability to look under the hood. An important Jython tool that helps when looking inside objects is Jython’s self-documentation convention called doc strings. These are anonymous string literals appearing in function, method, and class definitions.
Listing 1.7 defines a function called foo
. The second line of this example is an anonymous string literal, and a doc string because of its location. Note that this string is one indention level in as it should be as part of foo
’s code block. This doc string uses the triple-quote notation, but that is not required. Any legal string quoting works; triple-quotes just make it easier in case the documentation grows to more than one line.
Example 1.7. Documentation Strings, __doc__
>>> def foo(): ... """This is an example doc string""" ... pass ... >>> dir(foo) ['__dict__', '__doc__', '__name__', 'func_closure', 'func_code', 'func_defaults', 'func_doc', 'func_globals', 'func_name'] >>> foo.__doc__ 'This is an example doc string' >>>
The function dir()
is a built-in function that looks at name bindings within a namespace. Listing 1.7 uses dir
to look at function foo
, and returns a list of names defined inside foo
. In this list it is __doc__
. Looking at the contents of foo.__doc__
show that it is the name bound to the doc string provided in the function definition. The actual results of calling dir(foo)
differs between Jython 2.0 and Jython 2.1a1 (the current version as of this writing). Do not be concerned if your output differs slightly.
This section includes definitions and usage examples of Jython statements. Statements are categorized into simple statements, those with a single clause, and compound statements, those with multiple clauses or an associated code block.
Simple statements are those Jython statements with a single clause, encompassing one logical line. These statements are often confused with built-in functions; however, there is a distinction. Statements are part of the syntax as opposed to functions or data objects defined within a namespace.
The following sections list Jython’s simple statements and their syntax, and provides an example usage.
The assert
statement tests whether an expression is true and raises an exception if it is not true. If two expressions are supplied, the second expression will be used as the argument to the raised AssertException
. Setting __debug__=0
, and possibly the -O
command-line switch in future releases, disables asserts.
Syntax:
"assert" expression [, expression]
Example:
>>>a=21 >>>assert a<10 Traceback (innermost last): File "<console>", line 1, in ? AssertionError:
An assignment binds an object to an identifier. Jython has simple assignment (=
) and augmented assignments (
+
=
, -=
, *=
, /=
, *
*
=
, %=
, <
<
=
, >
>
=
, &=
, |=
, ^=
).
Syntax:
variable assignment-operator value
Example:
>>>var=3 >>>print var 3 >>>var += 2 >>>print var 5
The break
statement terminates execution of an enclosing loop and continues execution after the loop block. This means it does skip the else
block if it exists.
Syntax:
break
Example:
>>>for x in (1,2,3,4): ... if x==3: ... break ... print x ... 1 2 >>>
The continue
statement halts execution of the current loop block and start the enclosing loop again at its next iteration.
Syntax:
continue
Example:
>>>for x in (1,2,3,4): ... if x==3: ... continue ... print x ... 1 2 4 >>>
The del
statement removes a variable.The variable can be one within the namespace or a specific list or dictionary value.
Syntax:
"del" identifier
Example:
>>>a="foo" >>>print a foo >>>del a >>>print a Traceback (innermost last): File "<console>", line 1, in ? NameError: a>>> >>> a = [1,2,3] >>> del a[1] >>> print a [1, 3]
The exec
statement executes Jython code. The exec
statement requires an expression, which represents the code it needs to execute. A string, open file object, or code object can be supplied for this expression, which is the first parameter to exec()
. If two parameters are provided, the second is used as the global dictionaries in which the code is executed. If three parameters are provided, the first is a dictionary used as the global namespace, and the second is the local namespace in which the code is executed.
Syntax:
"exec" expression ["in" expression ["," expression]]
Example:
>>>exec "print 'The exec method is used to print this'" The exec method is used to print this >>>
The global
statement tells the parser to use global name bindings for listed identifiers throughout the current code block. Why? Because an assignment in a local code block identifies all references to that assigned variable as local. It’s easier to see in the comparison of the following two code snippets:
>>>var = 10 >>>def test(): ... print var # try and print the global identifier 'var' ... >>>test() 10 >>>
We see that var
is found and prints. So far, so good. Now, what happens if we assign something to var
after the print
statement?
>>>var = 10 >>>def test(): ... print var # try and print the global identifier 'var' ... var = 20 # assign to 'var' in local namespace ... >>>test() Traceback (innermost last): File "<console>", line 1, in ? File "<console>", line 2, in test NameError: local: 'var' >>>
The identifier var
is designated as local because of the assignment within the code block, so the print
statement is an error because var
does not exist yet in the local namespace. This is the reason for global
.
Syntax:
global identifier ["," identifier]*
Example:
>>>var = 10 >>>def test(): ... global var # must designate var global first. ... print var # try and print the global identifier 'var' ... var = 20 # assign to 'var' in local namespace ... >>>test() 10 >>>print var # check global 'var' 20 >>>
The import
statement locates and initializes what is imported and binds it to variables in the scope that import was called in. You can optionally change the name of the variables imports are bound to with an as
new-name
suffix to the import
statement.
Syntax:
import module-name OR from module-name import names OR import module-name as new-name OR from module-name import name as new-name
Example:
>>>import sys >>>from java import util >>>import os as myOS >>>from sys import packageManager as pm
The “do nothing” statement. This statement is a placeholder.
Syntax:
pass
Example:
>>>for x in (1,2,3,4): ... pass ... >>>
The print
statement evaluates an expression, converts the result to a string if needed, and writes the string to sys.stdout
or whatever file-like object it is directed to with the >>
syntax. A file-like object is one with a write
method defined.
Syntax:
print [expression] OR print >> fileLikeObject, [expression]
Example:
>>>print "Hello world" Hello world
The raise
statement evaluates any expressions provided with it and raises an exception accordingly.
Syntax:
raise [expression [, expression [, traceback]]]
Example:
>>>raise ValueError, "No value provided" Traceback (innermost last): File "<console>", line 1, in ? ValueError: No value provided
The return
statement ends execution of the method or function it is called in after evaluating any provided expression for use as a return value. If no expression is provided, the value None
is returned.
Syntax:
return [expression]
Example:
>>>def someFunction(): ... return "This string is the return value"
Compound statements are those statements that have a grouping or “block” of code associated with them. Flow control statements such as if
, for
, and while
are compound statements. These are difficult to introduce without mentioning Jython’s block indentation syntax. A code block, or grouping of statements, in Java is contained in braces {}
. Multiple levels of groupings are in nested braces { {} }
. This is not so for Jython. Rather, Jython uses the colon, :
, and indentation to identify blocks of code. With this knowledge, we can define Jython’s compound statements. The following sections explain Jython’s compound statements and their definitions.
The class
statement is used to define a class. Evaluation of a class
statement defines a class in that current scope. Calling a class calls its constructor if defined and returns an instance of that class.
Syntax:
"class" name[(base-class-name)]:
Example:
>>>class test: # no base class ... pass # place holder ... >>>t = test() # Calls class statement to make an instance
The def
statement is how functions and methods are defined.
Syntax:
"def" name([parameters]): statements
Example:
>>>def hello(person): ... print "Hello ", person ... >>>hello("world") # calls the hello function Hello world
The for
statement is a flow-control statement that iterates through a loop once for each member of a sequence. The for
statement can also include an optional else
clause that is executed after the sequence has expired.
Syntax:
"for" variable "in" expression":" statements ["else:"] statements
The expression provided must evaluate to a list.
Example:
>>>for x in (1,2,3): ... print x, ...else: ... print "in else clause" ... 1 2 3 in else clause >>>
The if
statement executes a block of code conditionally when an expression evaluates to true.
Syntax:
if expression: statements elif expression: statements else: statements
If the first expression evaluates to false, the interpreter proceeds to evaluate the elif
expression if provided. If all elif
conditions are false, the else
group of statements is executed.
Example:
>>>if a==b: ... print "variable a equals variable b" ...elif a>b: ... print "variable a is greater than b" ...else: ... print "variable a is less than b"
The try
statement executes a block of code until completion or until an error.
Syntax:
"try:" statements "except" ["," expression ["," variable]]":" statements ["else:" statements] OR ["finally:" statements]
Only one of the else
or finally
clause can be used, not both. If the try
block of code runs without error, it proceeds to execute the block of code in its finally
block. If the try
block has an error, it stops execution of that block and proceeds to the except clause.
Example:
>>>try: ... 1/0 ...except ZeroDivisionError, e: ... print "You cannot divide by zero: ", e ... You cannot divide by zero: integer division or modulo >>>
Table 1.1 lists the statements used in Jython and compares them with Java’s implementation.
Table 1.1. Jython Statements Compared to Java’s
Statement |
Comparison |
---|---|
|
The |
|
Jython and Java are similar in assignments despite there being some operator and scoping differences addressed later in this book. |
|
Jython and Java |
|
Jython and Java |
|
The |
|
This has been confused with being a parallel to Java’s |
|
Java does not have a direct parallel to Jython’s |
|
Java’s Java: import javax.servlet.*; Jython: from javax.servlet import * |
|
Java does not require a “do nothing” placeholder like |
|
|
|
Jython’s |
|
Jython and Java |
|
Jython and Java’s |
|
Method signatures in Java use a lot of information that Jython does not use. A signature like |
|
The main difference is that Jython’s Java: for (int x=10; x > 0; x++) Jython for x in (10, 9, 8, 7, 6, 5, 4, 3, 2, 1): Fortunately, Jython has the Jython: for x in range(10, 0, -1): Java also lacks the optional |
|
Jython’s |
|
|
|
Jython and Java |