Python的親戚們 (之三)

來源:互聯網
上載者:User

 

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.