免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1036 | 回复: 0
打印 上一主题 下一主题

Get to know Jython [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-02-28 09:42 |只看该作者 |倒序浏览
alt.lang.jre: Get to know Jython
Enhance your productivity on the Java platform
  

  Document options
  Print this page

  E-mail this page

  Sample code


Rate this page
  Help us improve this content



Level: Introductory
Barry Feigenbaum, Ph.D. (
feigenba@us.ibm.com
), Sr. Consulting IT Architect, IBM
06 Jul 2004
Get to know Jython, in this first article in a new series introducing alternate languages for the Java Runtime Environment, alt.lang.jre. Jython is an implementation of the popular scripting language Python, but running on a JVM. For Python developers Jython is the best possible entry point to the Java platform; for Java developers it may be the strongest incentive to learn another language. Frequent developerWorks contributor and alternate language enthusiast Barry Feigenbaum introduces Jython and shows you what it can do to enhance your productivity on the Java platform.
Welcome to the new series alt.lang.jre. While most readers of this series are familiar with the Java language and how it runs on a cross-platform virtual machine (part of the JRE), fewer may know that the JRE can host languages besides the Java language. In its support for multiple languages (including some that pre-exist the Java platform) the JRE provides a comfortable entry point for developers coming to the Java platform from other backgrounds. It also gives developers who have rarely, if ever, strayed from the Java language the opportunity to explore the potential of other languages without sacrificing the familiarity of the home environment.
The ability to choose the right language for a variety of development scenarios is a tremendous advantage for almost any developer, but particularly those working on complex enterprise systems. Likewise, the adaptability of the JRE to multiple languages only solidifies the standing of the Java platform as an enterprise development environment.
This series of articles is a survey of many of the alternate languages for the JRE. Most of the languages you'll learn about in the series are open source and may be used for free, while a few are commercial products that must be purchased. Many are characterized as "scripting" languages that promote programmer productivity over machine efficiency; others are ports of popular mainstream languages. In all cases, the languages are supported by the JRE and are believed, by the authors, to enhance the dynamic and flexible nature of the Java platform.
In this first installment in the series, I'll focus on Jython, a scripting language that combines the ease of use of the Python language with the power and flexibility of the Java Runtime Environment . I've selected Jython as the first language to be introduced in this series because it is, in my opinion, among the most mature and productive of the alternate languages for the JRE. As such, my exploration of Jython will focus on the productivity enhancements it can lend to your Java programming efforts. Future installments in this series will introduce Groovy, JRuby, Rhino, Nice, and NetRexx, and many other exciting alternate languages for the JRE.
CLR vs JRE? No contest!
Microsoft has recently been promoting the .NET platform's Common Language Runtime (CLR) based on its ability to run multiple languages. Microsoft claims that language adaptability makes .NET a better development environment than the Java platform, which it claims is a single-language environment. As this series of articles will show, the Java platform is far more adaptable than Microsoft would have you believe. The JRE supports many languages other than the Java language, including some that pre-exist the Java platform. While the JRE does not support all the same languages as the CLR, it does provide a remarkably varied language landscape. In fact, the JRE compares favorably to the CLR as a multi-language development environment, as readers of this series will soon discover.


The case for Jython
Jython is an implementation of Python that fully supports the Python 2.1 syntax and most of its semantics while running on a JVM. It is an interpreted, interactive, object-oriented programming language that is written in 100% pure Java and seamlessly integrated with the Java platform. As such, Jython is both remarkably easy to learn and use and capable of running in any environment that supports a JVM -- including Microsoft Windows, Mac OS, and most Unix and Linux variants. Jython can also fully utilize all the classes and APIs provided by the Java Runtime Environment.
Jython's exceptional productivity lies in its marriage of the ease of use and flexibility of a scripting language, Python, with the robustness of the Java platform. Its simple, English-like syntax and intuitive semantics make Jython an ideal language for existing Python programmers, entry-level programmers, or programmers seeking a very rapid application development platform. Its string and text support features make it an exceptional platform for writing text-processing programs. And its built-in string manipulation functions (including regular expressions), as well as procedural and convenience features make it the ideal language for creating simple "scripting" programs.
Jython compares favorably to Visual Basic in its easy entry and adaptability, to many scripting languages in its emphasis on functionality, and to the Java language in both power and reliability. It is both a strong functional programming language and (by virtue of its object-oriented and modularized architecture) an excellent language for developing large applications.
In the following sections, I'll look closely at the mechanics underlying this powerful and versatile language.

Back to top


Features of Jython
Jython syntax is line-oriented and similar to English while fully supporting the structured and object-oriented programming styles of languages such as Java and C++. Jython code can be directly interpreted or it can be translated to Java source that is automatically compiled to class files (see Resources). Compiled Jython classes can be executed independently from the Jython interpreter or used from Java code as if they were Java classes (for example, to develop applets or servlets).
Install and run the sample code
To run the Jython code samples in this article, you will need to have both Jython and a JRE installed. You can get Jython from the Jython home page and the Java platform from the Java platform home page (see Resources). Both of these sites include easily followed installation instructions. The samples in this article assume you have added the Jython install directory (which contains the jython.bat file) to your PATH.


As previously stated, Jython's productivity is its strongest asset. Some of the unique features of Jython (as compared to the Java language) are as follows:
Code can be entered and run line-by-line in interactive mode, which can improve learning and promote experimental use.
Variables are dynamically typed on assignment, so there is no need to pre-declare variables or use the new operator. These enhancements can significantly increase programming flexibility and also reduce the text size of your programs, thus increasing your productivity.
String operations are extensive and easily accessed (for example, x == y in Jython is the same as x.equals(y) in the Java language).
Adapter objects are automatically generated and automatically provide default Java interface implementations, making it much easier to implement event handler callbacks.
Natural indefinite precision integer values (that is, trivial access to a java.math.BigInteger-like type) and natural complex values allow Jython to easily support many more mathematical applications than are supported by the Java language.
Dynamic attributes (each class instance acts like a Java Map) allow far more dynamic class functionality.
Enhanced importing (like Java 1.5's import static) increase flexibility and modularity.
Classless and mainless (that is, open) code increase productivity for procedural programs (such as scripts).
Multiple public variables, functions, and/or classes per source file reduce the number of source files you must maintain, which simplifies large-scale development.
Default arguments on functions and methods greatly reduce the number of overloaded methods you need to create.
Keyword arguments on functions and methods increase the self-documentation and flexibility of your code.
Functional programming (functions are first-class objects) provide a very powerful and flexible style of programming that is lacking in the Java language.
Multiple inheritance supports a much richer inheritance hierarchy for the problems that require it.
Operator overloading allows new data types to be created that seamlessly integrate into the language.
What's classy about 'first class'?
First class entities can be represented as literal values, placed in variables and collections and passed as inputs and results of function calls. Thus, the primitive data types of the Java language, such as int, float, etc., are not first class. Generally an entity must be an object to be first class. In Jython all commonly used data types are first class.


This list gives you a good overview of the structural utility of Jython. In the sections that follow, I'll describe some of the elements that comprise Jython's productivity advantage -- namely data types and statement types.

Back to top


First class data types
Jython supports many data types. All are first class and all are objects. Most support a literal representation that greatly simplifies their use. Many are more convenient to use than Java's types, especially the collection types. The most frequently used Jython data types are described in Table 1.
Table 1. Summary of Jython data types
Type Comment  Example
Null An undefined value (like null in the Java language). None
Integer A normal (int in the Java language) or long (BigInteger in the Java language) integer number. -1  0  100
-1L  1000000000000000000000000000000000000000000001L

Float  A fractional or exponential (like double in the Java language) number. 1.0
-1e6  0.000001e-10  1E11

Complex  A pair of floats supporting complex arithmetic.  1j  -10J
2-3j  1e6j


String  An immutable sequence of characters. There is no character type (use one character strings instead).  "a string"
'a string'
"""a long (possibly multi-line) string"""
'''another (possibly multi-line) long string'''
r'''^xxx(.*?)\.yyy(.*?)\.zzz(.*?)\.$'''
'x'  "y" '\n' "\\"


Range  An immutable sequence of integers.  range(10)
range(10,0,-1)
xrange(1,100000,10)


Tuple  An immutable sequence of any type (like java.util.Collections.unmodifiableCollection(someList)).  ()  (1,)  (1,2,3)
(1, "mixed", 2, "tuple")
((1,2),(3,4))


List  A mutable sequence of any type (like java.util.ArrayList).  []  [1]  [1,2,3]
[1, 'mixed', 2, 'list']
[[1,2],[3,4]]


Map  A mutable collection of items (name/value pairs) (like java.util.Map). Names must be immutable and unique; values may be None.  {}
{1:'one',2:'two',3:'three'}
{"one";1, "two":2, "three":3}
{"x":1, "ints":(1,2,3),
"name":{"first":"Barry", last":"Feigenbaum"}}


Boolean  A true/false value based on other types.  false - 0 or empty: None
0  0.0
()  []

true - non-0, not empty: 1  -1  0.0001
[1]  [1,2,3]  {"greeting":"Hello!"}


Function  Any function. Functions do not need to be members of classes.  lambda x: x > 0
def isPositive(x): return x > 0
def addem(x,y,z):
    return x + y + z


Class  Any class. Classes are namespaces for class attributes and functions (called methods).  class MyClass:
    x = 1
    y = 2
class subclass(superClass):
    def method1(self): ...
    def method2(self, arg1, arg2): ...


Module  A source file (and namespace) that contains variable, function and/or class definitions.  Any .py file that defines importable variables, functions and/or classes. If it does not define any of these then it is just called a script.  

Back to top


Statement types
Jython provides the statement types summarized in Table 2.
Table 2. Summary of Jython statement types
Statement  Comment  Examples  
Expression  Any expression. The results are discarded. Often used for their side effects.  (1 * 2) ** 3 / 4
"string"[2:] == "ring"
someFunction(1, 2, 3)


Assignment  Assigns an expression to a target.  x = 3
x = f(1,32,3) * 10 + x
list[1:3] = [7, 8, 9 , 10]


Augmented Assignment  Updates a target with an expression.  x *= 100
s += "…"


Unpacking Assignment  Assigns elements of a sequence to multiple targets; very convenient for access to tuple and list members. Note that the expression 1,2,3 is a short form of (1,2,3).  x,y,z = 1,2,3


Multiple Assignment  Assigns the same expression to multiple targets.  z = y = z = 10


Pass  No operation.  pass


If
If/Else
If/Elif/Else  Conditional processing.  if x
if x == 3:
    print "It's three!"
if   x == 1: ...
elif x == 2: ...
elif x == 3: ...
else: print "Bad value " + x


While  Looping over a condition.  x = 10
while x > 0:
    print x   
    x -= 1


For  Iterates over a sequence. Use range to iterate over a numeric sequence.  for i in range(10): print i
for c in "A string":
    print c
for i in (10, "Hello", 1e6):
    print func(i)


Continue  Advances to the next loop (while/for) iteration.  for i in range(10):
    if not testOk(i):
        continue
    :


Break  Exits a loop (while/for)  for i in range(10):
    if testBad(i):
        break
    :


Delete  Removes a variable or sequence element(s) or class attribute.  del x
del list[3:5]
del x.attr1


Global  Declares a reference to a global value; used in functions.  x,y,z = 0,1,2
def f(a,b,c):
    global x,y,z
    :


Print  Prints expression(s) to a stream.  print "Hello World!"
print "Hello","World!"
print "Hello" + ' ' + "World!"
msg = "Name: %(last)s, (first)s"
data = {'last':"Feigenbaum", 'first':"Barry"}
print >>out, msg % data


Assert  Asserts a condition is true.  
def process(v):
    assert v > 0, "Illegal value %i" % v
    :


Import  Imports all or part of a module.  import sys
from sys import argv
from javax import swing
from java.util import Map


Execute  Executes a string/file as a subprogram. There is also a related function, exec, that executes a constructed string and returns its result. This support allows you to dynamically create programs.  globals = {'x':1, 'y':2, 'z':3}
locals = {'list':(1,2,3)}
code = "print x, y, z, list"
exec code in globals, locals


Try/Except  Executes code within an exception handler.  try:
    x = int(string)
except ValueError, e:
    x = 0


Try/Finally  Executes code with a cleanup routine.  f = open("test.dat")
try:
    lines = f.readlines()
finally:
    f.close()


Raise  Creates and throws an exception.  def factorial(x):
    raise ValueError, "x must be > 0"
    :


Define  Defines a function; arguments may be optional and/or keywords; Functions are generic which allows for very flexible programming.  def f(x,y=2,z=10): return x+y+z
q = f(1,2) + f(3) + f(4,5,6)
s = f("a","b","c")


Return  Returns from a function with an optional value.  return 10


Class  Defines a class (a container for attributes and methods) .  class X: pass
class MyClass(SomeClass):   
    pass



Back to top


Let's see it in code!
At this point you should have a growing understanding of the structure and syntax of Jython. What remains is best learned by examining a few simple but complete working programs. I'll start with the quintessential example program -- Hello World! -- which looks as follows in Jython:
Listing 1. Jython's Hello World!
print "Hello World!"

In Jython (as in Python) source files use the extension "py". The "Hello World" statement is a complete program when placed in a source file such as hello.py.
For comparison, take a look at the equivalent Java program, seen here in a file such as hello.java:
Listing 2. Java's Hello World!
public class hello {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

The Jython form is clearly much simpler, which is frequently the case. The nice thing about Jython, of course, is that the code can be directly interpreted or it can be translated to Java source and automatically compiled to class files. You can run the Hello World program by using the following Java command:
C:\>java -Dpython.home=C:\jython-2.1 -cp C:\jython-2.1\jython.jar
      org.python.util.jython hello.py

Or, you can run the program by using the more convenient Jython script below:
C:\>jython hello.py


Back to top


Echo, echo, echo.py!
Next, you'll try a more functional example, with a small program that lets you echo command-line arguments. For the program echo, you use the following code (in echo.py):
Listing 3. Example program for echoing command-line arguments
import sys
count = 1
for arg in sys.argv[1:]:
    print 'Argument %i=%s' % (count, arg)
    count += 1

Again, this complete Jython program reveals some key features of Jython. The first thing you'll note is that each line is a statement -- semicolons (;) are not required to end lines -- and that variables are not declared.
You should also note that command-line arguments are accessed via the built-in symbol sys.argv that is a sequence of strings. sys is a standard module that contains useful values and functions; many other standard modules exist for you to use. The first argv element (0) is the program name (that is, echo.py). To skip it you take a slice of the argv list, effectively starting at position one (1), and then iterate through the end of the list.
Looping is done via the for statement group. The for body is the indented lines after the for. The print statement demonstrates the use of Jython's string formatting feature (similar to C/C++'s printf and the new print feature of Java 1.5).
The above code could also be written more concisely as follows:
from sys import argv
for i in range(1, len(argv)): print 'Argument %i=%s' % (i, argv)

In this case, you use a range to index the sys.argv list. Because the argv variable is directly imported qualification is not required. Notice that the length of the argv list is obtained through the len function and not as a method; this is a Jython idiom and is common in many languages. Many other functions exist for you to use.

Back to top


Let's factor -- with factorial.py!
For an exercise in class definition, you'll use the caching factorial calculator of factorial.py, shown in Listing 4.
Listing 4. The caching factorial calculator
class Factorial:
    ''' A factorial calculator '''
    seen = {} # cache of prior calculated values   
    def __init__ (self, value):
        self.__value = value
    def compute (self, value=None):        
        ''' calculate the result '''
        if value is None: value = self.__value   # default
        if   value
Here you see many new features of Jython. First off, comments are introduced by the sharp (#) token. A class or method can have a documentation comment string (which can be processed by tools similar to how JavaDoc is used) as its first line. Other than for assignment, statements are introduced by keywords. Class and method bodies are not enclosed in delimiters but are instead indicated by indention of their bodies.
Furthermore, classes are declared by the class statement. The def statement introduces methods. Class attributes are created by assignment in the class while instance attributes are created by assignment in the constructor method __init__. The seen variable is a dictionary. Instances are created by calling the class object as a function. Methods are invoked (as in the Java language) with the dot (.) operator.
You'll also note that the self variable is the method's receiver (like this in the Java language); within a method all references to instance attributes or methods of the class must be qualified with self. Class variables (as in the Java language) are qualified by the class name.
Functions can have default arguments, as shown for the value argument of the compute function. If the parameter value is omitted, then the __value instance attribute is used.
At this point it has become obvious that Jython supports all the features of the Java language but sometimes with different syntax. For example, Jython's raise statement is the same as the Java language's throw statement.
Testing factorial.py
You can test your Factorial class using the following code, which you'll also find in the file factorial.py (see Resources):
if __name__ == "__main__":
    from sys import argv
    if   len(argv) == 1: vals = range(10)
    elif len(argv) == 2: vals = range(int(argv[1]))
    elif len(argv) == 3: vals = range(int(argv[1]), int(argv[2]))
    else: print " Incorrect range"; vals = ()
    for i in vals:
        print "Factorial(%i)=%i" % (i, Factorial(i).compute())
    print "Cache:", Factorial.seen

In Jython, class definitions and tests cases can be combined. The if __name__... test above allows the test case code to run only if this file is run as a command. The file may also be imported by another file to reuse the Factorial class without running the test case. The test case consists of some simple command argument processing followed by a loop that calculates the factorial of the specified values (if any). Finally, the cache of values is printed.The jython factorial.py 5 10 command produces the following output:
Factorial(5)=120
Factorial(6)=720
Factorial(7)=5040
Factorial(8)=40320
Factorial(9)=362880
Cache: {9: 362880L, 8: 40320L, 7: 5040L, 6: 720L, 5: 120L, 4: 24L, 3: 6L, 2: 2L}

You might also notice in the example above that indefinite length integers can be calculated through the Jython long type (###L).

Back to top


A GUI example
I'll end this introduction to Jython with a more complex program that creates a GUI. As you consider the simple AWT-based application, you'll see firsthand Jython's ability to be called from Java code and to access all the features of the Java platform.
You'll start by creating a GUI that is a Java Panel subclass called Scribble, as shown in Listing 5. Later, you'll create a Frame to display the Panel.
Listing 5. Class Scribble is a subclass of a Java Panel
from java.awt import BorderLayout as BL, Color, Button, Panel
class Scribble(Panel):
    """ A simple GUI example """
    def __init__ (self):  # constructor
        Panel.__init__(self, BL())
        self.add(Button('Clear', actionPerformed=self.doClear),
                         BL.SOUTH)
        self.mouseDragged = self.doDrag
        self.mousePressed = self.doPress
        self.__last = 0, 0
    def doClear (self, event):
        """ clear background """
        g = self.graphics
        g.color = self.background  
        g.fillRect(0, 0, self.size.width, self.size.height)
    def doDrag (self, event):
        """ draw line from last to here """
        g = self.graphics
        g.color = Color.black
        lx, ly = self.__last
        x = event.x; y = event.y
        g.drawLine(lx, ly, x, y)   # draw new line segment
        self.__last = x, y   # save coordinates
    def doPress (self, event):
        """ save click point """
        self.__last = event.x, event.y
if __name__ == "__main__":
    def doClose (event):
        import sys
        sys.exit()
    from java.awt import Frame
    frame = Frame("Scribble", windowClosing=doClose)
    frame.add( Scribble() )
    frame.size = 400, 300
    frame.visible = 1

The first thing you'll likely notice about the code in Listing 5 is that multiple statements have been placed on one line, using semicolons as a separator. Lines can be continued after a comma. The import statement can import multiple classes and optionally rename them. The import statement is executable so it can be placed where needed, avoiding importing unnecessary symbols. Notice the nested doClose function. Also notice the lack of declarations and the lack of a new operator when creating class instances.
The self.__last instance attribute (which is a private attribute because it starts with a double underscore) holds the previous mouse click position. Each time a mouse drag event occurs, a (possibly quite short) black line is drawn between the saved point and the location of the event.
Notice also how the event handlers are defined. No Listener interface is used; instead attributes that match the interesting event handler entry points defined by the class (for example, actionPerformed) are set to Jython functions. The other unused entry points, if any, are automatically mapped to empty functions, thus there is no need to use Adapter classes. Also notice that any JavaBeans properties of Java objects (such as for the Graphics object g) can be accessed as Jython properties, not via get/set methods. This simplifies coding significantly, although you can still use the get/set methods if you like.
Figure 1 shows the Scribble GUI in use.
Figure 1. Sample Scribble GUI


Back to top


Conclusion
Sean McGrath, CTO of Propylon and frequent author, has said of Jython that it is the "most awesome Java productivity tool" without major vendor backing, and has also called it "the most compelling weapon the Java platform has for its survival into the Twenty-first century." In this first installment of alt.lang.jre, you've seen for yourself the ease and efficiency that Jython can bring to your development efforts on the Java platform. I've also begun, briefly, to discuss the importance of multi-language support to the future of the Java platform.
Next month you can continue your exploration of alternate languages for the JRE with an introduction to Groovy, a new language that combines some of the best aspects of Python, Ruby, and Smalltalk into an efficient, easy, and fun scripting language for the Java platform.
In the meantime, of course, there's lots more to be said about Jython, but it would take a book. See the Resources section to learn more about this powerful, easy-to-use language.

http://www-128.ibm.com/developerworks/java/library/j-alj07064/


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/19919/showart_485570.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP