jython_Jython简介,第2部分:编程要点

关于本教程

本教程是关于什么的?

这是分两部分的教程的第二部分,旨在向您介绍Jython脚本语言。 Jython是已与Java平台无缝集成的Python实现。 Python是一种功能强大的面向对象的脚本语言,主要在UNIX环境中使用。

在本教程的第1部分中,您学习了Jython的基础知识,包括安装和设置,访问选项和文件编译,语法和数据类型,程序结构,过程语句和函数。 在第2部分中,我们将深入研究使用这种强大的脚本语言的一些更高级的方面,首先是对Jython的面向对象编程的深入介绍。 我们还将讨论任何语言对应用程序开发机制必不可少的主题,包括调试,字符串处理和文件I / O。

到您完成Jython的两部分介绍的下半部分时,您将能够在Jython中编写和实现完整的功能,类和程序。

我应该学习本教程吗?

本教程旨在逐步介绍Jython。 如果您尚未完成本教程的第1部分 ,则应在继续进行第2部分之前完成。如果不参考第1部分 ,那么概念性讨论和此处介绍的许多代码示例将很难遵循。

在本教程的后半部分,我们将介绍使用Jython编写脚本的以下方面:

  • 使用Jython进行面向对象的编程
  • 调试
  • Java支持
  • 字符串处理
  • 文件I / O
  • 在Jython中构建Swing GUI应用程序

要从讨论中受益,您应该熟悉至少一种过程编程语言和计算机编程的基本概念,包括命令行处理。 要充分利用Jython的功能,您还应该熟悉面向对象编程的基本概念。 为了完全理解本教程结尾处的GUI应用程序示例,您应该具有Swing GUI编程的先前经验,尽管您将能够从前面的讨论和示例中学到很多东西。 熟练掌握Java平台也将很有帮助,因为Jython运行在JVM上。 尽管这不是本教程的要求。

请注意,本教程是针对Windows系统的。 所有命令示例都将使用Windows语法。 在大多数情况下,相似的命令在UNIX系统上执行相同的功能,尽管不会演示这些命令。

工具,代码和安装要求

您必须在开发系统上安装Jython 2.1或更高版本才能完成本教程。 您的开发系统可以是与命令提示符结合使用的任何ASCII文本编辑器(例如Windows记事本)。 本教程包括有关在系统上获取和安装Jython的详细说明。

要使用Jython,您还必须在系统上安装Java运行时环境(JRE)。 建议您使用最新的JRE(在撰写本文时为1.4.2),但是Java 1.2或更高版本的任何版本都可以正常工作。 如果要在浏览器中使用Jython(即作为小程序),则必须至少对浏览器有JRE 1.1可用。 请参阅“ 相关主题”部分以下载最新版本的JDK。

本教程中的所有代码示例均已在Windows 2000上的Sun Java 1.4.1 JRE上运行的Jython上进行了测试。示例在其他操作系统上的任何类似配置上均应保持不变。

本教程包括一组附录,详细介绍了您将用来了解Jython的所有代码示例。 所有代码示例均已在Windows 2000的Sun Java 1.4.1 JRE上运行的Jython上进行了测试。这些示例在其他操作系统上的任何类似配置上均应保持不变。

Jython中的面向对象编程

概念概述

面向对象编程(OOP)代表了软件编程技术的最新发展。 OOP基于在程序中创建目标问题的模型 (或仿真)的概念。 正确使用OOP技术可减少编程错误,加快软件开发速度,并促进现有代码的重用。 Jython完全支持OOP的概念和实践。

在以下各节中,我将介绍OOP并描述如何在Jython中实现。 在下一节中,我将讨论Jython中面向对象编程的一些更高级的功能。

Jython中的对象

Jython是一种面向对象的语言,完全支持面向对象的编程。 Jython定义的对象具有以下功能:

  • 身份 :每个对象都必须是不同的,并且必须是可测试的。 为此,Jython支持isis not测试。
  • 状态 :每个对象都必须能够存储状态。 Jython为此提供了属性 (又名字段或实例变量 )。
  • 行为 :每个对象必须能够操纵其状态。 Jython提供了用于此目的的方法 。

请注意, id(object)内置函数返回唯一的整数标识值。 因此,表达式x is y等于id(x) == id(y)

Jython中的OOP支持

在对面向对象编程的支持中,Jython包括以下功能:

  • 基于类的对象创建 :Jython 类是用于创建对象的模板。 对象是具有相关行为的数据结构。
  • 具有多态性的继承 :Jython支持单 继承和多继承 。 所有Jython实例方法都是多态的 (或virtual ),并且可以被子类覆盖。
  • 隐藏数据的封装 :Jython允许(但不要求)隐藏属性,因此仅允许通过类的方法在类外部进行访问。 类实现函数(称为方法)来修改数据。

定义班级

定义类非常类似于定义模块,因为可以定义变量和函数。 与Java语言不同,Jython允许每个源文件(或模块)定义任意数量的公共类。 因此,Jython中的模块非常类似于Java语言中的软件包。

我们使用class语句在Jython中定义类。 class语句具有以下形式:

class name ( superclasses ):  statement

  -- or --

class name ( superclasses ): 
    assignment
     :

    function
     :

定义类时,可以选择提供零个或多个赋值语句。 这些创建由类的所有实例共享的类属性。 您还可以提供零个或多个函数定义。 这些创建方法。 超类列表是可选的。 我们将在本教程的稍后部分讨论超类。

类名在相同范围(模块,函数或类)中应该唯一。 类名实际上是绑定到类主体的变量(类似于任何其他分配)。 实际上,您可以定义多个变量来引用同一类。

创建一个类实例

类用于保存类(或共享)属性或创建类实例。 要创建类的实例,您可以像调用一个函数一样调用该类。 无需像C ++或Java语言那样使用新的运算符。 例如,与类

class MyClass:
    pass

以下语句创建一个实例:

x = MyClass()

向类实例添加属性

在Jython中(不同于Java语言),客户端可以将字段 (也称为attribute )添加到实例。 仅一个实例被更改。 要将字段添加到实例( x ),只需在该实例上设置新值,如下所示:

x.attr1 = 1
x.attr2 = 2
  :
x.attrN = n

定义类属性和方法

绑定到类中的任何变量都是类属性 (或变量)。 在类中定义的任何函数都是方法 。 方法接收该类的实例(通常称为self )作为第一个(可能是唯一的)参数。 例如,要定义一些类属性和方法,可以输入:

class MyClass:
    attr1 = 10        # class attributes
    attr2 = "hello"

    def method1(self):
        print MyClass.attr1   # reference the class attribute

    def method2(self, p1, p2):
        print MyClass.attr2   # reference the class attribute

    def method3(self, text):
        self.text = text    # instance attribute
        print text, self.text    # print my argument and my attribute

    method4 = method3       # make an alias for method3

请注意,在类内部,应使用类名称(例如MyClass.attr1 )限定对类属性的所有引用,并使用self变量(例如self.text )对所有实例属性的引用进行限定。 在类之外,应该使用类名(例如MyClass.attr1 )或实例(例如x.attr1 )来限定对类属性的所有引用,并使用实例(例如x.text )来x.attr1对实例属性的所有引用x.text ,其中x是该类的实例)。

隐藏变量

为了实现数据隐藏,通常需要创建“私有”变量,该变量只能由类本身访问。 Jython提供了一种命名约定,使在类之外访问属性和方法变得困难。 如果您声明以下形式的名称: __xxx或__xxx_yyy (这是两个下划线),则Jython解析器将自动修改(即,将类名添加到)声明的名称,实际上创建了隐藏变量。 例如:

class MyClass:
    __attr = 10               # private class attribute

    def method1(self):
        pass        

    def method2(self, p1, p2):
        pass       

    def __privateMethod(self, text):
        self.__text = text    # private attribute

请注意,与C ++和Java语言不同,对实例变量的所有引用都必须使用self限定; 有没有隐含使用this

初始化方法

__init__方法充当实例构造函数的角色。 每当创建实例时都会调用它。 应该为所有类定义此方法。 方法__init__可以接受参数。 在Jython中,与C ++或Java语言不同,所有实例变量(也称为属性或字段)都是通过赋值动态创建的。 它们应该在__init__内定义(即分配给)。 这样可以确保为后续使用方法定义它们。 一些示例如下:

class Class1:
    def __init__ (self):             # no arguments
        self.data = []               # set implicit data

class Class2:
    def __init__ (self, v1, v2):     # 2 required arguments
        self.v1 = v1                 # set data from parameters
        self.v2 = v2

class Class3:
    def __init__ (self, values=None): # 1 optional argument
        if values is None: values = []
        self.values = values          # set data from parameter

del方法

如果您在__init__方法(或任何其他方法)中分配了任何资源,则需要确保在释放对象之前释放这些资源。 最好的方法是使用__del__方法。 在垃圾回收器释放对象之前,将调用__del__方法。 您还应该提供可以直接调用的清理方法(通常称为closedestroydispose )。 这是一个例子:

class Class:
    def __init__ (self, db):    
        self.connection = db.getConnection()    # establish a connection
        self.connection.open()

    def __del__ (self):                         # cleanup at death
        self.close()

    def close(self):                            # cleanup
        if not self.connection is None and self.connection.isOpen():
            self.connection.close()             # release connection
        self.connection = None

使用类作为值

也可以将类分配给变量(包括函数参数)。 从以下通用类实例工厂可以看出,这使得基于类编写动态代码变得非常容易:

def instanceMaker(xclass, *args):
    return apply(xclass, args)

 :

x = instanceMaker(MyClass)   # same as: x = MyClass()

遗产

从类继承的能力是面向对象编程的基础。 Jython支持单继承和多继承。 单一继承意味着只能有一个超类。 多重继承意味着可以有多个超类。

继承是通过对其他类进行子类化来实现的。 这些类可以是其他Jython类或Java类。 任何数量的纯Jython类或Java接口都可以是超类,但是只能(直接或间接)继承一个Java类。 您不需要提供超类。

超类中的任何属性或方法也都在任何子类中,并且可由类本身或任何客户端使用(假定它是公开可见的)。 只要可以使用超类的实例,就可以使用子类的任何实例-这是多态的一个示例。 这些功能使重用,快速开发和易于扩展成为可能。

以下是继承的一些示例:

class Class1: pass                # no inheritance

class Class2: pass

class Class3(Class1): pass        # single inheritance

class Class4(Class3,Class2): pass # multiple inheritance

from java import awt
from java import io         

# inherit a Java class and interface and a Jython class
class MyPanel(awt.Panel, io.Serializable, Class2): 
    :

具有继承的init方法

子类的__init__方法必须调用为其父类定义的任何__init__方法。 这不是自动的。 下面的两个示例演示了如何将__init__方法与继承一起使用。

class Class1(SuperClass):
    def __init__ (self):               # no arguments
        SuperClass.__init__(self)      # init my super-class
        self.data = []                 # set implicit data

class Class2(SuperClass):
    def __init__ (self, v1, v2):       # 2 required arguments
        SuperClass.__init__(self, v1)  # init my super-class with v1
        self.v2 = v2

以下是一些使用多重继承进行初始化的示例:

class Class1(Super1, Super2):
    def __init__ (self):               # no arguments
        Super1.__init__(self)          # init each super-class
        Super2.__init__(self)
        self.data = []                 # set implicit data

class Class2(Super1, Super2):
    def __init__ (self, v1, v2, v3):   # 3 required arguments
        # note you may do work before calling the super __init__ methods
        self.v3 = v3                   # set data from parameter
        Super1.__init__(self, v1)      # init each super-class
        Super2.__init__(self, v2)

调用超类方法

您可以通过使用类名限定任何超类方法来调用它,如下所示:

class Class1:
    def method1 (self):             
        :

class Class2(Class1):
    def method1 (self):         # override method1
        :
        Class1.method1(self)    # call my super-class method
        :

    def method2 (self):             
        :

class Class3(Class2):
    def method1 (self):         # override method1
        :
        Class2.method1(self)    # call my super-class method
        :

    def method3 (self):             
        :

请注意,辅助方法定义(在Class2Class3 )将覆盖超类定义。 不需要子类方法调用其超类方法; 但是,如果没有,则必须完全替换超类方法的功能。

调用方式

调用方法有两种语法(假设您有一个由变量mci引用的MyClass实例):

  • mci.someMethod(...)
  • MyClass.someMethod(mci, ...)

第一种形式通常用于类客户端编码中,而第二种形式通常用于子类中以调用超类方法。

先进的面向对象编程

从理论到实践

在本节中,我们将从Jython中的面向对象编程的概念概述转到更高级的讨论,其中包含诸如运算符重载,特殊属性和自省之类的主题。

特殊属性

Jython类为几种特殊属性提供支持。 最重要的信息如下所示:

名称 角色 注释)
__dict__ 对象的可写属性 可用于内省对象的属性
__class__ 对象的类别 访问对象的类(类似于Java编码中的x.getClass()
__bases__ 对象的直接超类的元组 可用于内省对象的超类

更改现有实例的类

与大多数其他语言不同,在Jython中,您可以更改现有实例的类。 这样做会将您可以在实例上使用的方法更改为新类的方法,但不会更改其任何现有字段。 例如,要更改实例的类,请将新类分配给__class__特殊属性(请参见特殊属性 ),如下所示:

x = SomeClass()               
print isinstance(x, SomeClass)       # prints: 1 (true)
print isinstance(x, SomeOtherClass)  # prints: 0 (false)
 :
# change the class (that is, the type) of the instance here
x.__class__ = SomeOtherClass  
print isinstance(x, SomeClass)       # prints: 0 (false)
print isinstance(x, SomeOtherClass)  # prints: 1 (true)

y = SomeOtherClass()               
print x.__class__ == y.__class__     # prints: 1 (true)

进行此更改之后, x实例将支持SomeOtherClass的方法,而不是以前的SomeClass 。 更改对象的类时,请注意实例具有新类的正确属性。

自省属性示例

这是一个使用特殊属性的实际示例(请参阅特殊属性 )。 模块printclass.py可以内省类和实例以显示其属性和方法。 稍后再讨论内省,或者您可以查看内省 。 您还可以查看String操作和函数以及附录K:内置函数,以了解有关下面使用的函数的更多信息。 现在,仅关注callable函数, vars函数(隐式使用__dict__属性)和__bases__属性的使用。

__any__ = ['getMembers', 'printObject']

def addMember (list, item):
    if not item in list:
        list.append(item)

def getMembers (obj, memtype="attrs"):
    """ Get all the members (of memtype) of the object. """
    members = []
    for name, value in vars(obj).items():
        try:
            item = obj.__name__, name, value
        except:
            item = "<instance>", name, value
        if   memtype.lower().startswith("attr"):
            if not callable(value):
                addMember(members, item)
        elif memtype.lower().startswith("meth"):
            if callable(value):
               addMember(members, item)
        elif memtype.lower() == "all":
            addMember(members, item)
    try:
        for base in obj.__bases__:
            members.extend(getMembers(base, memtype))
    except:
        pass
    return members

import sys

def printObject (obj, stream=sys.stdout):
    """ Print all the members of the object. """
    members = getMembers(obj, "attrs")
    members.sort() 
    print >>stream, "Attributes:"
    for objname, memname, value in members:
        print >>stream, "  %s.%s" % (objname, memname)

    members = getMembers(obj, "methods")
    members.sort() 
    print >>stream, "Methods:"
    for objname, memname, value in members:
        print >>stream, "  %s.%s" % (objname, memname)

自省属性示例测试用例

下面的代码使用上一部分中的函数来内省UserList类。 有关UserList类的定义,请参见运算符重载

if __name__ == "__main__":

    from UserList import UserList
    
    class MyClass(UserList):
        def __init__ (self, x, y):
            UserList.__init__(self)
            self.__x = x
            self.__y = y
    
        def method1 (self):
            return self.x + self.y
    
        def method2 (self, x, y):
            return  self.x + self.y + x + y

    print "For class:", `MyClass`
    printObject(MyClass)
    print 

    aMyClass = MyClass(1, 2)
    aMyClass.extend([1,2,3,4])
    print "For instance:", `aMyClass`
    printObject(aMyClass)

获取成员的输出

以下输出(重新格式化为多列以节省空间)是上述模块中运行主代码的结果。 请注意,私有字段和方法(请参阅隐藏变量 )具有错误的名称。

For class: <class __main__.MyClass at 28921555>
Attributes:            Methods:                     
  MyClass.__doc__        MyClass.__init__         UserList.__len__            
  MyClass.__module__     MyClass.method1          UserList.__lt__             
  UserList.__doc__       MyClass.method2          UserList.__mul__            
  UserList.__module__    UserList._UserList__cast UserList.__ne__             
                         UserList.__add__         UserList.__radd__           
                         UserList.__cmp__         UserList.__repr__           
                         UserList.__contains__    UserList.__rmul__           
                         UserList.__delitem__     UserList.__setitem__        
                         UserList.__delslice__    UserList.__setslice__       
                         UserList.__eq__          UserList.append             
                         UserList.__ge__          UserList.count              
                         UserList.__getitem__     UserList.extend             
                         UserList.__getslice__    UserList.index              
                         UserList.__gt__          UserList.insert             
                         UserList.__iadd__        UserList.pop                
                         UserList.__imul__        UserList.remove             
                         UserList.__init__        UserList.reverse            
                         UserList.__le__          UserList.sort               

For instance: [1, 2, 3, 4]
Attributes:                    
  <instance>._MyClass__x
  <instance>._MyClass__y
  <instance>.data

Methods:

请注意,方法和类属性与类一起驻留,实例属性与实例一起驻留。 但是,所有类的方法都可以应用于每个实例。

内省

您通常需要在运行时确定对象的特征。 我们称这是对对象的自省 。 Java平台通过java.lang.Class类和java.lang.reflect包中的类提供自省服务。 尽管功能强大,但这些API还是有些难以使用。 您可能已经怀疑过,Jython提供了一种更简单的内省方法。

在Jython中,我们可以使用dirvars函数检查任何对象的绑定,例如模块,函数,类,序列,映射等。 为了更好地了解其工作原理,请考虑以下示例。 输出已插入到以“ ...”为前缀的print语句之后(并重新格式化),以便于阅读。 dir函数仅返回绑定名称,而vars函数返回名称和值; 因此,当两个函数返回相同的名称时,我们只需要使用vars函数,如下所示:

#-- empty start --
print "vars:", vars()
...vars: {'__doc__': None, '__name__': '__main__'}

x = 1
y = 2
z = 3
l = [x, y, z]
d = {x:"xxxx", y:"yyyy", z:"zzzz"}

#-- locals variables --
print x, y, z, l, d
...1 2 3 [1, 2, 3] {3: 'zzzz', 2: 'yyyy', 1: 'xxxx'}

#-- plus locals variables --
print "vars:", vars()
...vars: {'__name__': '__main__', 'x': 1, \
... 'd': {3: 'zzzz', 2: 'yyyy', 1: 'xxxx'}, '__doc__': None, \
... 'y': 2, 'l': [1, 2, 3], 'z': 3}

import sys

#-- plus import --
print "vars:", vars()
...vars: {'__name__': '__main__', 'z': 3, 'l': [1, 2, 3], \
... '__doc__': None, 'y': 2, 'x': 1, 'sys': sys module, \
... 'd': {3: 'zzzz', 2: 'yyyy', 1: 'xxxx'}}

#-- sys import --
print "vars sys:", vars(sys)  
...vars sys: {'classLoader': \
...     <beanProperty classLoader type: java.lang.ClassLoader at 31845755>, 
...     ... many values removed ...,
... 'warnoptions': <reflected field public static \
...     org.python.core.PyList \
...     org.python.core.PySystemState.warnoptions at 1024901>}

del x, y, z

#-- post delete --
print "vars:", vars()
...vars: {'__name__': '__main__', 'l': [1, 2, 3], '__doc__': None, \
... 'sys': sys module, 'd': {3: 'zzzz', 2: 'yyyy', 1: 'xxxx'}}

def func (x, y):
    return x, y

class MyClass ():
    def __init__ (self, x, y):
        self.__x = x
        self.__y = y

    def method1 (self):
        return self.x + self.y

    def method2 (self, x, y):
        return  self.x + self.y + x + y

#-- plus function and class --
print "vars:", vars()
....vars: {'func': <function func at 21569784>, '__name__': '__main__', \
...  'l': [1, 2, 3], '__doc__': None, \
.... 'MyClass': <class __main__.MyClass at 1279942>, \
...  'sys': sys module, 'd': {3: 'zzzz', 2: 'yyyy', 1: 'xxxx'}}

#-- function --
print "dir: ", dir(func)     # **** dir and vars different here ****
print "vars:", vars(func)
...dir:  ['__dict__', '__doc__', '__name__', 'func_closure', \
... 'func_code', 'func_defaults', 'func_doc', 'func_globals', 'func_name']
...vars: None

#-- class --
print "vars:", vars(MyClass)
...vars: {'__doc__': None, '__init__': <function __init__ at 17404503>, \
... 'method2': <function method2 at 23511968>, '__module__': '__main__', \
... 'method1': <function method1 at 28670096>}

myclass = MyClass(1, 2)

#-- instance --
print "myclass:", myclass
print "vars:", vars(myclass)
...myclass: <__main__.MyClass instance at 19014134>
...vars: {'_MyClass__y': 2, '_MyClass__x': 1}

请注意, dir(x)通常等效于x.__dict__.keys()vars(x)通常等效于x.__dict__

自省的附加功能

特殊属性中描述的属性允许对类进行其他自省。 特别是,您可以使用__dict__属性来确定类中的方法和实例中的字段。

除了dirvars ,Jython还提供了更多用于自省类和实例的函数,如下所示:

功能 注释)
hasattr(obj, name) 测试以查看命名属性是否存在
getattr(obj, name {, default}) 获取命名属性(如果存在); 否则,返回默认值(如果没有提供默认值,则引发异常)
setattr(obj, name, value) 设置命名属性的值
delattr(obj, name) 删除命名属性

请参阅附录K:内置功能以了解有关这些功能的更多信息。

抽象类

抽象类是其中某些或所有方法均缺失或定义不完整的类。 必须创建一个子类来提供或完成这些方法定义。 具体的类不是抽象的(也就是说,所有方法都是完整的)。 到目前为止,我们仅与具体的类一起工作。 创建抽象类以促进重用。 它们提供了设计的部分实现,您可以通过将其子类化来完成或扩展设计。

为了更好地了解其工作原理,我们将创建一个简单的抽象命令框架,该框架支持命令doundoredo操作。 命令在(子)类中定义,可以通过创建新的do_...undo_...方法轻松添加。 如前几节所述,我们通过自省访问了这些方法。

抽象命令框架

这是示例抽象命令框架:

class CommandProcessor:   # an abstract class
    """ Process Commands. """

    def __init__ (self):
        self.__history = []
        self.__redo = []

    def execute (self, cmdName, *args):
        """ Do some command """
        self.__history.append( (cmdName, args) )
        processor = getattr(self, "do_%s" % cmdName, None)
        if processor:
            return processor(*args)
        else:
            raise NameError, "cannot find do_%s" % cmdName

    def undo (self, count=1):
        """ Undo some (or all) commands in LIFO order """
        self.__redo = []
        while count > 0 and len(self.__history) > 0:
            cmdName, args = self.__history.pop()
            count -= 1
            processor = getattr(self, "undo_%s" % cmdName, None)
            if processor:
                self.__redo.append( (cmdName, args) )
                processor(*args)
            else:
                raise NameError, "cannot find undo_%s" % cmdName

    def redo (self, count=1):
        """ Redo some (or all) undone commands """
        while count > 0 and len(self.__redo) > 0:
            cmdName, args = self.__redo.pop()
            count -= 1
            processor = getattr(self, "do_%s" % cmdName, None)
            if processor:
                processor(*args)
            else:
                raise NameError, "cannot find do_%s" % cmdName

注意:此示例基于Samuele Pedroni和Noel Rappin的Jython Essentials中的代码( 有关更多信息,请参见参考资料)。

示例框架的测试用例

这是示例抽象命令框架的测试用例:

class MyProcessor (CommandProcessor):  # a concrete subclass
    def __init__ (self):
        CommandProcessor.__init__(self)

    def do_Cmd1 (self, args):
        print "Do Command 1:", args

    def do_Cmd2 (self, args):
        print "Do Command 2:", args

    def do_Cmd3 (self, args):
        print "Do Command 3:", args

    def undo_Cmd1 (self, args):
        print "Undo Command 1:", args

    def undo_Cmd2 (self, args):
        print "Undo Command 2:", args

    def undo_Cmd3 (self, args):
        print "Undo Command 3:", args

mp = MyProcessor()

print "execute:" ; mp.execute("Cmd1", None)
print "execute:" ; mp.execute("Cmd2", (1,2,3))
print "execute:" ; mp.execute("Cmd3", "Hello")
print "undo:   " ; mp.undo(2)
print "redo:   " ; mp.redo(2)

print "execute:", ;mp.execute("BadCmd", "Hello")

具有给定测试用例的框架将产生以下输出:

execute:
Do Command 1: None
execute:
Do Command 2: (1, 2, 3)
execute:
Do Command 3: Hello
undo:   
Undo Command 3: Hello
Undo Command 2: (1, 2, 3)
redo:   
Do Command 2: (1, 2, 3)
Do Command 3: Hello
execute:
Traceback (innermost last):
  File "cmdproc.py", line 63, in ?
  File "cmdproc.py", line 15, in execute
NameError: cannot find do_BadCmd

运算符重载

与C ++一样,但与Java语言不同,Jython允许许多标准语言运算符被类重载。 这意味着类可以为语言运算符定义特定的含义。 Jython还允许类模拟内置类型,例如数字,序列和映射。 要了解有关仿真的更多信息,请参见附录B:常见的重载运算符和方法

在下面的示例中,我们将使用标准的Jython UserList类定义来展示实际中的运算符重载的示例。 UserList是包装列表并像列表一样工作的类。 它的大部分功能都被委托 (传递给)了它所包含的列表,称为data 。 在更现实的示例中,将实现这些重载功能以访问某些其他存储,例如磁盘文件或数据库。

class UserList:
    def __init__(self, initlist=None):
        self.data = []
        if initlist is not None:
            if   type(initlist) == type(self.data):
                self.data[:] = initlist
            elif isinstance(initlist, UserList):
                self.data[:] = initlist.data[:]
            else:
                self.data = list(initlist)

    def __cast(self, other):
        if isinstance(other, UserList): return other.data
        else:                           return other

    #  `self`, repr(self)
    def __repr__(self): return repr(self.data)

    #  self < other
    def __lt__(self, other): return self.data <  self.__cast(other)

    #  self <= other
    def __le__(self, other): return self.data <= self.__cast(other)

    #  self == other
    def __eq__(self, other): return self.data == self.__cast(other)

    #  self != other, self <> other
    def __ne__(self, other): return self.data != self.__cast(other)

    #  self > other
    def __gt__(self, other): return self.data >  self.__cast(other)

    #  self >= other
    def __ge__(self, other): return self.data >= self.__cast(other)

    #  cmp(self, other)
    def __cmp__(self, other):
        raise RuntimeError, "UserList.__cmp__() is obsolete"

    #  item in self
    def __contains__(self, item): return item in self.data

    #  len(self)
    def __len__(self): return len(self.data)

    #  self[i]
    def __getitem__(self, i): return self.data[i]

    #  self[i] = item
    def __setitem__(self, i, item): self.data[i] = item

    #  del self[i]
    def __delitem__(self, i): del self.data[i]

    #  self[i:j]
    def __getslice__(self, i, j):
        i = max(i, 0); j = max(j, 0)
        return self.__class__(self.data[i:j])

    #  self[i:j] = other
    def __setslice__(self, i, j, other):
        i = max(i, 0); j = max(j, 0)
        if   isinstance(other, UserList):
            self.data[i:j] = other.data
        elif isinstance(other, type(self.data)):
            self.data[i:j] = other
        else:
            self.data[i:j] = list(other)

    #  del self[i:j]
    def __delslice__(self, i, j):
        i = max(i, 0); j = max(j, 0)
        del self.data[i:j]

    #  self + other   (join)
    def __add__(self, other):
        if   isinstance(other, UserList):
            return self.__class__(self.data + other.data)
        elif isinstance(other, type(self.data)):
            return self.__class__(self.data + other)
        else:
            return self.__class__(self.data + list(other))

    #  other + self   (join)
    def __radd__(self, other):
        if   isinstance(other, UserList):
            return self.__class__(other.data + self.data)
        elif isinstance(other, type(self.data)):
            return self.__class__(other + self.data)
        else:
            return self.__class__(list(other) + self.data)

    #  self += other  (join)
    def __iadd__(self, other):
        if   isinstance(other, UserList):
            self.data += other.data
        elif isinstance(other, type(self.data)):
            self.data += other
        else:
            self.data += list(other)
        return self

    #  self * other   (repeat)
    def __mul__(self, n):
        return self.__class__(self.data*n)
    __rmul__ = __mul__

    #  self *= other  (repeat)
    def __imul__(self, n):
        self.data *= n
        return self

    # implement "List" functions below:

    def append(self, item): self.data.append(item)

    def insert(self, i, item): self.data.insert(i, item)

    def pop(self, i=-1): return self.data.pop(i)

    def remove(self, item): self.data.remove(item)

    def count(self, item): return self.data.count(item)

    def index(self, item): return self.data.index(item)

    def reverse(self): self.data.reverse()

    def sort(self, *args): apply(self.data.sort, args)

    def extend(self, other):
        if isinstance(other, UserList):
            self.data.extend(other.data)
        else:
            self.data.extend(other)

嵌套类

像函数一样,类可以嵌套。 Jython中的嵌套类的工作方式类似于Java语言中的静态内部类。 这是一个例子:

class MyDataWrapper:
    class Data: pass    # inner data structure class

    def __init__ (self):
        self.data = Data()

    def set (self, name, value):
        setattr(self.data, name, value)

    def get (self, name, default=None):
        return getattr(self.data, name, default)

调试Jython <

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值