Python的亲戚们 (之三)

来源:互联网 发布:数据库datetime 格式 编辑:程序博客网 时间:2024/04/28 04:26

 

http://blog.csdn.net/idisposable

First Eye on Boo Language

 

在.NET平台上,除了IronPython之外,Python还有另外一个亲戚 - Boo。

但是Boo语言并不真正是Python语言的实现,它只是有着和Python一样的外衣而已。

 

===========================================================

下面是我读BooPrimer的学习笔记,:)

1. 跟其他的语言教程一样,BooPrimer也是从"hello, world"开始。

print "Hello, World!"

或者

print ("Hello, World")

是不是跟Python中一样?在Python 2.6及以前的print statement采用前一种形式;在Python 3.0之后,print已经成为了一个函数。Boo支持两种形式,我想也是为了和Python兼容吧。

BooPrimer推荐使用宏(print "Hello, World!")的形式,跟Python中的发展方向不一致。下面看看这二者编译之后的代码吧(编译之后用.NET Reflector查看的代码)。

(a) print "hello, world" 编译后的代码是:
Console.WriteLine("hello, world")

(b) print ("hello, world")编译后的代码:
Builtins.print("hello, world")

至于Builtins.print具体做了什么,有兴趣的读者可以自己去看看。

2. String interpolation (字符串插入)

String interpolation让字符串格式化变得很方便。看看例子:

toy = "kitty"
print "hello, ${toy}"

这里能够插入到字符串中的可以是任何合法的Boo表达式。当展开字符串时,Boo会计算该表达式,然后调用表达式结果的ToString方法。可以写几行简单的代码验证这一点。代码如下:

class TestObject:

    def ToString():

        return "This is an instance of class TestObject"

obj = TestObject()

s = "Result: ${obj}"

3. 在Boo中所有的所有都是对象

这一点不用多解释了,Boo和Python一样 - 在它们的世界里,什么都是对象,内建基础数据类型(如整型,字符,字符串),代码段,解释器都是对象。甚至类型本身也是对象(先前没有接触过Python/Boo的也许会觉得这很疯狂吧)。

>>> obj as object
>>> print obj == null
>>> true
>>>

主要上面的代码中用了as关键字显式地指定了对象的类型。这也是Boo区别与Python的一个地方 - 可以指定对象的类型来增强安全性。而且有一点一定别忘记:Boo并不是真正动态类型的语言,所以对象在其生命周期中类型是固定的。

4. 检测对象的运行时类型(Runtime type of an object)
跟Python不同,Boo因为基于.NET,它的类型系统也是使用.NET的Common Type System (CTS)。

检测对象的方式也和.NET一致。

(a) obj.GetType()

(b) typeof

不过我发现typeof一点都不好用。如下所示:

 

>>> l = [1, 2, 3]
>>> typeof(l)
Error: The name 'l' does not denote a valid type.
>>> t = l.GetType()

Boo.Lang.List
>>> typeof(t)
Error: The name 't' does not denote a valid type.
>>> typeof(Boo.Lang.List)
>>> Boo.Lang.List
>>>

typeof跟Python中的type()比较起来显得太死板了。

 

5. 内建函数 (Builtin Functions)

Boo支持一些内建函数如 print, gets, prompt, join, map, array, matrix, iterator,
shellp, shell, shellm, enumerate, range, reversed, zip, cat等。

 

6. 自定义函数

Boo中自定义函数的语法和Python是一样的。但是对于成员函数的定义和Python有些不同,我将在以后的系列文章中详述。

这里是几个自定义函数的例子:
def Hello():
    print "hello"

#这个函数指定了返回值类型
def Hello() as string:
    print "hello"

def Hello(name):
    print "hello, ${name}"

#这个函数指定了参数的类型
def Hello(name as string):
    print "hello, ${name}"


为参数和返回值指定类型使得程序安全性提高了,Boo可以对参数和返回值进行类型检查。

 

7. Overloading
Boo在函数重载方面做的比Python好很多。来看简单的例子吧。

def Hello():

    return "Hello, World!"

 

def Hello (name as string):

    return "Hello, ${name}!"

 

def Hello(num as int):

    return "Hello, Number ${num}!"

 

def Hello(name as string, other as string):

    return "Hello, ${name} and ${other}!"

 

8. 可变参数

Boo也支持可变参数。e.g.


>>> def Test(*args as (object)):
>>>    return args.Length
>>> print Test("hey", "there")

2
>>> print Test(1, 2, 3, 4, 5)

5
>>> print Test("test")

1

 

>>> a = (7, 9, 8)
>>> print Test(*a)

按照BooPrimer最后一个测试Test(*a)应该返回3。 但是实际使用Boo 0.7.6的结果是出错:

ERROR: The best overload for the method 'Input27Module.test(*(object))' is not compatible with the argument list '(*(int))'.

 

9. 属性和字段 (property and field)

Boo区别property和field,这对于.NET程序员来说比较舒服。也可以在Boo中通过attribute来定义properties。

class Cat:
    [Property(Name)] // 这是一个属性。通过对它的访问来读写字段_name
    _name as string // 这是一个字段,不能从类的外部访问,应该使用属性来访问它。

看下边的setter/getter是不是跟C#里边的很象啊?

class Cat:

    [Getter(Name)]

    _name = 'Meowster'


    [Setter(FavoriteFood)]

    _favoriteFood as string

 

fluffy = Cat()

print fluffy.Name

fluffy.FavoriteFood = 'Broccoli'

 

上边的setter/getter都是隐式的形式,再来看看显式属性的例子。
class Cat:
    Name as string:
        get:
            return _name
        set:
            _name = value
    _name as string


9.1 Pre-condition of property
class Cat:

    [Property(Name, Name is not null)]

    _name as string

 

fluffy = Cat()

fluffy.Name = null # 对Name属性设置空值会引发ArgumentException异常

不知道C#中有没有相似的特性?

 

10. Class modifiers
public, protected, internal, protected internal, private, abstract, final

"public" is assumed if no modifier is specified

Boo向.NET学习定义了一堆的class modifiers, 这样细粒度的访问控制能够满足更好的安全性。

11. interface support
这是Boo相对于Python的一个优点 - 从语言层支持接口的概念。 

e.g.
interface IFeline:
    def Roar()
    Name:
        get
        set

12.值类型和引用类型

和.NET一样, 所有的类(class)都是引用类型;基础类型为值类型,如int, long, double, bool, byte等。值类型永远都拥有值(不能设置为null),他们有缺省值,例如数值类型的缺省值为0。

 

13. Class member methods

定义成员方法和Python的语法类似,不同点在于不需要self关键字。

class Cat:

    def Roar():

        print "Meow!"

cat = Cat()

cat.Roar()

 

14. 构造函数和析构函数 (Constructor and Destructor)

class Cat:

    def constructor():

        _name = "Whiskers"

    def destructor():

        print "${_name} is no more..."

    [Getter(Name)]

    _name as string

 

cat = Cat()

print cat.Name

因为.NET的不确定性析构的问题,所以你的代码不能够依赖析构函数被调用。你不知道它什么时候会被调用,也许永远都不会。

 

15. Method modifiers

abstract: 抽象方法

static: 静态方法

virtual, override - 虚方法和方法重写。

这些都和C#/.NET是一致的。

 

16. Member visibility

成员的可见性分为几种: public, protected, provate

如果没有显式声明,所有的字段缺省都是protected, 而方法(methods),属性(properties)和事件(events)缺省都是public。

 

17. 在构造函数中声明属性 (Declaring Properties in the constructor)

这是一个比较好用的语言特性,算是语法糖吧。

class Box:

    def constructor():

        pass

    [Property(Value)]

    _value as object

 

box = Box(Value: 42)

print box.Value

 

18. 多态和继承

多态和继承是面向对象的两个本质特性。Boo语言中的多态和继承没有什么特别的地方,跟C#语言一样,这样不再赘述。

 

19. 结构体 (structs)

Boo语言中的结构体完全是从.NET借过来的。结构体是值类型,也可以定义自己的方法。

e.g.

struct Rectangle:

    def constructor(w as int, h as int):

        _w = w

        _h = h

 

    _x as int

    _y as int

    def Area():

        return _w * _h

 

20. 名字空间 (namespace)

跟Python相比这的确是个好东西 - Python只能借用module来对付名字冲突。

20.1 声明名字空间

在文件头部这样来声明名字空间

namespace MyNamespace

 

class TypeInTheNamespace():

    pass

 

如果需要导入另外的名字空间呢?也很简单,就想C#一样。

import System

import MyNamespace

import Gtk from "gtk-sharp"  // quoted because there is a special character '-'.

 

21. 枚举 (enumerations)

没有什么特别的地方,看例子吧。

enum Day:

    Monday

    Tuesday

    Wednesday

    Thursday

    Friday

    Saturday

    Sunday

 

class Action:

    [Property(Day)]

    _day as Day

 

22. 异常 (exceptions)

抛出异常 (raising exceptions)

e.g.

import System

def Execute(i as int):

    if i < 10:

        raise Exception("Argument must be greater or equal to 10.")

    print i

 

捕获异常 (catching exceptions)

捕获异常有三种形式:try-except, try-ensure, 和try-except-ensure

看看下边的例子。

# try-except example

import System

try:

    print 1 / 0

except e as DivideByZeroException:

    print "oops"

print "Doing other stuff"

 

# try-ensure example

import System

try:

    s = MyClass

    s.DoSomethingBad()

ensure:

    print "This code will be executed, whether there is an error or not."

这里的ensure跟C#的finally是等同的东西。

 

try-except-ensure是上边两种形式的结合。

# try-except-ensure example

import System

try:

    s = MyClass

    s.DoSomethingBad()

except e as Exception:

    print "Problem! ${e.Message}"

ensure:

    print "This code will be executed, whether there is an error or not."

 

23. 函数调用和多线程 (functions as objects and multithreading)

在Boo中,一切都是对象,所以函数也不例外。每个函数都有三个方法:

Invoke: 跟正常调用函数一样

BeginInvoke: 启动一个工作线程来运行这个函数

EndInvoke: 等待先前启动的线程完成函数调用并返回计算结果。

因为Boo提供便利的异步函数调用,多线程编程变得很容易。

 

24. generators (生成器或生成子,怎么翻译都觉得难听)

用过Python的读者对generator一定不陌生。

generator 表达式的语法定义:

<expression> for <declarations> [as <type>] in <iterator> [if|unless <condition>]

e.g.

>>> List(x for x in range(5)) // 最简单的形式

[0, 1, 2, 3, 4]

>>> List(x for x in range(5) if x % 2 == 0)

[0, 2, 4]

 

generator 方法:

gemerator方法使用yield关键字,这样的方法看起来象普通的方法但是能够给调用者多次返回。

是不是难明白,看看例子就知道了。

def TestGenerator():

    i = 1

    yield i

    for x in range(10):

        i *= 2

        yield i

 

print List(TestGenerator())

 

generator是继承自IEnumerable,所以可以和for ... in 一起使用。

 

25. 宏 (macros)

Boo提供了几种宏让编程更便利。不过我有一个疑问:不知道Boo是否支持用户自定义的宏?

 

print Macro

这个我们已经熟悉了。 e.g.

print "Hello there"

print "Hello", "there"

print "first", "second", "third", "more", "more and more"

 

assert macro

这个是防御性编程的宝贝。

assert true // 总是会通过

assert false, "message" // 总是会失败

 

using macro

跟C# 中的using 用法一样,为受保护对象提供了一个生命周期控制。

e.g.

using w = StreamWriter("test.txt"):

    w.WriteLine("Hello there!")

 

lock macro

和C#一样,lock macro用来在多线程环境下同步对象的访问。

e.g.

lock database:

    database.Execute("UPDATE messages SET id = id + 1")

debug macro

和print Macro类似,不同点在于print输出到System.Console, 而debug macro输出到System.Diagnostics.Debug。

 

26. Duck typing

也许不翻译是最容易理解的了,:)

definition: duck typing is a humorous way of describing the type non-checking system. initially coined by Dave Thomas in the Ruby community, its premise is that (referring to a value) "if it walks like a duck, and talks like a duck, then it is a duck."

 

Even though Boo is a statically typed language, Duck Typing is a way to fake being a dynamic language. Duck typing allows variables to be recognized at runtime, instead of compile time. Though this can add a sense of simplicity, it does remove a large security barrier.

e.g.

d as duck

d = 5 // 现在d是一个整型

print d

d += 100 // 能够做任何整型允许的操作

d = "hello" // 闲杂d变成了字符串类型了

print d

d = d.ToUpper() // 可以执行任何字符串操作了

print d

 

================================================================================================================

Boo的学习笔记就到这里为止了。以后对它的了解多了再来写吧。

 

相关连接:

1. Boo http://boo.codehaus.org/ Boo的官方网站

2. SharpDevelop http://www.icsharpcode.net/OpenSource/SD/ 提供了一个Boo的IDE环境

3. IronPython的介绍 http://blog.csdn.net/IDisposable/archive/2008/10/08/3035790.aspx