2008年11月26日 星期三

簡單的 Server & Client for windows

這是從http://nxforce.blogspot.com/2008/07/cc-socket-connection.html看來的,非常的清楚!除了提供檔案下載,還逐行解釋,甚至連怎麼編譯都有交代。

不過對我這個菜鳥來說,看到gcc ..... -lwsock32 這個參數倒是挺陌生的 ...

原來這是 link 到 WindowAPI 的方法,我們可以在他提供的兩個檔案中看到
#pragma comment(lib,"wsock32.lib")


而這行就需要這個參數!雖然我還是不太了解 #pragma comme .. 的意思啦 ...


這裡可以看到許多 C code ,裡面有 echo server / client !
http://src.wtgstudio.com/list_user.php?uid=jackal

2008年11月25日 星期二

製作 sha1c.so on arm

本來是想 build vfs1.3 與 Mk4tcl 在 arm 上,讓 arm 可以直接 source critcl2.kit ,但無奈功力不足 ...

先是成功 build vfs1.3,但 tclsh critcl2.kit 時依舊有錯誤訊息,查了一下才發現它在 package require Mk4tcl 時出錯了。後來嘗試 build Mk4tcl ,還真是困難重重,編譯成功了,但卻無法 package require Mk4tcl 進來 ...

再來我就換個方向,換編譯 vqtcl ,原先 tclsh critcl2.kit 時,可以在 source code 裡面看到若是 Mk4tcl 有錯,就換 package require vfs::mkcl ,而 vqtcl 這個套件就內涵 vfs::mkcl,而這次比較順利,直接就編譯過去了,本想說終於可以在 arm 上玩 kit 檔案,卻還是出現這樣的錯誤訊息 ...

couldn't read file "/home/root/critcl2.kit/main.tcl": Success
while executing
"source /home/root/critcl2.kit/main.tcl"
("uplevel" body line 1)
invoked from within
"uplevel [list source [file join $self main.tcl]]"


看起來應該是 vqtcl 處理的不夠完整,無法直接 source .kit 內的檔案 ...

看來要在 arm 上玩 .kit 檔案要擇日再研究了!




回到正題,雖然無法在 arm 上把玩 kit 檔案,但依舊是可以用一些偷吃步的方法 ...!

必須要先有相關環境

在這邊下載 - sdx.bat、sdx.kit 兩個檔案
http://www.equi4.com/pub/sk/

在這邊下載 - Tclkitsh (for windows) (有些防毒軟體會認為它是病毒,但其實只是雙重副檔名造成誤判,因此只要記得下載時把副檔名 exe 拿掉即可)
http://www.equi4.com/pub/tk/downloads.html
此執行檔下載回來之後,記得更名為 tclkitsh.exe (配合 sdx.bat)


環境都有之後
先在 windows 底下,下達這樣的指令
sdx unwrap critcl2.kit


這時候就會出現 critcl2.vfs 的資料夾

裡面我們會用到的有

critcl2.vfs/lib/critcl/ -> 將其複製到 arm 上的 /usr/lib/tcl8.4 底下
critcl2.vfs/lib/platform/ -> 將其複製到 arm 上的 /usr/lib/tcl8.4 底下
critcl2.vfs/lib/app-critcl/critcl.tcl -> 複製到 arm 上任意資料夾,此為主要執行檔案
critcl2.vfs/lib/app-critcl/runtime.tcl -> 與上述檔案放在同一個資料夾內
(以上兩隻程式我是放在 /home/root/critcl4arm/ 底下)

到了這個階段,可以試試看執行 tclsh /home/root/critcl4arm/critcl.tcl ,應該會跳出 help 資訊。

有了以上環境,有了 gcc ,就可以開始編譯 .so 檔了!

sha1c 的 source code 在 tcllib 裡面有。
http://sourceforge.net/projects/tcllib/

抓下 tcllib-1.11.tar.gz 之後,tcllib-1.11\modules\sha1\ 裡面存放著許多檔案,但我們需要用到的只有 sha1c.tcl、sha1.c、sha1.h 這三個檔案,將這三個檔案放置在同一個資料夾,並進入此資料夾內下達這樣的指令

tclsh /home/root/critcl4arm/critcl.tcl -pkg sha1c.tcl


等待數秒,就可以看到此資料夾底下出現一個 lib/ ,而裡面所放的 sha1c/ 資料夾就是 sha1c 的 .so 套件了!將其移動到 /usr/lib/tcl8.4/ 裡,接下來就可以享受在 arm 上用 c 來演算 sha1 的神速了!

Tcl - sha1::sha1 -bin [string repeat a 500000]
約 20 秒

C - sha1::sha1 -bin [string repeat a 500000]
約 0.17 秒

2008年11月24日 星期一

Tcl extension 實作

這算是我開始學 C 的原因之一吧?雖然完全沒有用 C 實作一個成品出來,但至少對於 gcc 稍微有點感覺了。

說真的,Tcl extension 實作還真的可以完全不用研究 C ... 但花了兩天學了 C 之後,對於它的錯誤訊息卻非常有勇氣去處理跟閱讀,因此,我解決了它的錯誤 ... 如今,我也可以輕鬆的利用 Critcl 來用 C 寫出 Tcl 的 shared library 了!

首先必須先有 gcc 的 runtime,這其實只要安裝 dev-cpp,然後在環境變數裡新增 C:\Dev-CPP\bin 就可以了。

之後可以參考這個網站
http://www.garyfeng.com/wordpress/2002/11/20/critcl-builds-c-extensions-on-the-fly/

但照著這個網站去作,在 windows 上還是可能會出問題,由於 critcl 會自動在 ~ 目錄建立一個 .critcl 資料夾,而它會將需要編譯的檔案都放在裡面,開始編譯的階段,它會嘗試給 gcc 這些檔案的完整路徑,而問題就是在這邊發生的。

像這樣
gcc C:\Documents and Settings\user\......


可想而知是一定會出錯的 ...


解決的方法,一是將它指定的目錄改為非空白路徑,二是幫它處理好這段。這兩種方式都不會很困難。

之後就可以在 windows 上正常編譯出 .dll 檔案了!

2008年11月22日 星期六

C 語言學習 Part II

我好像都跳著記錄 ... 通常有疑惑的部分我才會自己寫個測試看看,所以感覺是測試筆記 ...

說不定沒測試的部分雖然看懂了但卻沒有記下來 ... !不過不管怎樣就繼續往下吧!



這一樣是從良葛格學習筆記繼續的。

這是直接從某位址放進字串的方法
#include <stdio.h>

int main(void) {
    
// 在 *str1 這個位址放入 h,然後依序放入 ello
    char *str1 = "hello";
    
    
// 偏移量為 0 即為 h 
    printf("%c\n", str1[0]);
    
    
// 偏移量加 1 即為 e 
    printf("%c\n", *(str1 + 1));
    
    
// 偏移量加 5 也是放了一個 '\0',與陣列字串一樣? 
    if (str1[5] == '\0') {
        
puts("如果偏移量加 5 的位址放了 '\\0' 就會看到這行");
    
}
}



釐清底下兩個例子
#include <stdio.h>

int main(void) {
    
// 這個例子要證明底下兩個是不同的
    
    
// 例子一
    char *str1[] = {"abc12", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "xy1", "234"};
    
    
// 例子二
    char str2[10][4] = {"abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "xy1", "234"};
    
    
printf("str1\t\t指向這個位址\t\t%X\n", str1);
    
    
printf("str1[0]\t\t的位址是\t\t%X\n", &str1[0]);
    
printf("str1[0]\t\t這個位址所存放的是\t%s\n", str1[0]);
    
    
printf("str1[1]\t\t的位址是\t\t%X\n", &str1[1]);
    
printf("str1[1]\t\t這個位址所存放的是\t%s\n", str1[1]);
    
    
// 這邊可以看的出來,它的空間會配合宣告而變動 
    printf("str1[0][6]\t這個位址所存放的是\t%c\n", str1[0][6]);
    
    
puts("");
    
    
printf("str2\t\t指向這個位址\t\t%X\n", str2);
    
    
printf("str2[0]\t\t的位址是\t\t%X\n", &str2[0]);
    
printf("str2[0]\t\t這個位址所存放的是\t%s\n", str2[0]);
    
    
printf("str2[1]\t\t的位址是\t\t%X\n", &str2[1]);
    
printf("str2[1]\t\t這個位址所存放的是\t%s\n", str2[1]);
    
    
printf("str2[0][4]\t這個位址所存放的是\t%c\n", str2[0][4]);
}

2008年11月21日 星期五

Hello World!

希望可以將基礎打好,因此還是從頭來過!

底下是參考了良葛格的學習筆記,並稍微修改成自己較容易記得的寫法。

這應該是最簡短的寫法了。
# include <stdio.h>

int main() {
    
printf("Hello World!\n");
}



雖然我指定 name 為 char ,但仍可以用 %d 將它印出來,只是會變為 66('A' = 65, 'B' = 66)
#include <stdio.h>

int main(void) {    
    
int age;
    
char name = 'B';
    
    
printf("%d\t%d\n", age, name);
}



甚至可以這樣做都不會出錯 ... 所以是否只是宣告記憶體配置空間而已呢?
#include <stdio.h>

int main(void) {    
    
int age = 'A';
    
char name = 65;
    
    
printf("%d\t%c\n", age, name);
}



這也令我非常困惑!
#include <stdio.h>

int main(void) {
    
// 照理說是宣告一個大小為 5 的陣列?但似乎有些隱藏的涵義? 
    char str[5];
    
printf("輸入 a 或是 b,不然就無法寫入 str:");
    
    
// 正規表示法? 
    scanf("%[a-b]", str);
    
printf("輸入的字元為 %s\n", str);    
    
    
// 不把暫存器中的東西清除的話,下次遇到 scanf 就會直接把暫存器中的東西拿去用而跳過去了 ... 
    fflush(stdin);
    
    
// 如果覆寫失敗,那 str 就會維持此行之前的內容 
    printf("輸入 1 或是 2,不然就無法覆寫 str:");
    
scanf("%[1-2]", str);
    
printf("輸入的字元為 %s\n", str);
    
    
// 為什麼這行不會出錯?而且若是上頭的 scanf 輸入了超過 10 個字以上,第 11 個字還會被取代成 a! 
    str[10] = 'a';
    
    
printf("%s\n", str);
    
    
// 厲害的是 size 還是 5? 
    printf("%d\n", sizeof(str));
    
    
return 0;
}



這裡要特別注意換行符號!
#include <stdio.h>

int main(void) {
    
// 一個字元 c 
    char c;
    
    
// 輸入超過一個字元,會將剩下的字元放進暫存區中 ... 等待下次的 getchar 或是 scanf 
    printf("請輸入一個字元:");
    
c = getchar();
    
    
// 若輸入了 a 並按下 Enter, 暫存器中會進行這樣的動作
    // 暫存器的值 = 'a\n', 取出第一個字元放進 c 並進行清除
    // 所以 c 將會存放 'a',且暫存器中仍有 '\n' 
    
    
    
// 直接印出 c 
    putchar(c);
    
putchar('\n');
    
    
// 若第一次輸入時輸入了超過一個字元,則這邊會將暫存器中的值再取出一個並清除
    // 若第一次輸入只輸入一個字元,這邊則會抓到換行符號! 
    c = getchar();
    
putchar(c);
    
putchar('\n');
    
    
return 0;
}



身為 Tcler ,這東西真的讓我感到非常親切 ......
#include <stdio.h>

int main(void) {
    
char c;
    
char str[20];
    
    
// 會直接加上換行符號 
    puts("請輸入字串:");
    
    
// 輸入一行字串且去掉換行符號 
    gets(str);
    
puts("輸入的字串為:");
    
puts(str);
    
    
// 這邊可以測試的出來 gets 會確實的將輸入的東西完全從暫存器中移除
    // 不會殘留換行符號在內,而是取出之後才處理!
    puts("如果這邊有停止的話,則暫存器內已無字元!請隨意輸入字元:"); 
    
c = getchar();
    
    
return 0;
}



今天先告一段落 ...

C 語言學習開始!

總是得起頭的,不是嗎?

儘管腳本語言在解決問題上迅速確實,但在面對效能問題時,還是得依靠 C 才有辦法克服。

Tcl 版本的 md5 演算法,在演算 500000 個 a 的時候,需要花費 20 秒(環境是在 arm9 上)
C 版本的 md5 演算法卻只要花費 0.17 秒 ...(環境是在 arm9 上)


更糟糕的是,雖然 Tcl 可以將 C source code 動態載入,但我依舊不知道該如何進行才好!

因為我根本不懂它們之間的關係 ...!真的只懂皮毛是不夠的 ...

2008年11月20日 星期四

Glade 的第一個 hello world

還真是辛苦 ...

網路上充斥著不能用的範例,大概是版本不同的關係 ... 搞了好久才弄出第一個 hello world ...

hello.py
# coding=utf-8

import gtk
import gtk.glade

class HellowWorld:
    
def __init__(self):
        
self.wTree = gtk.glade.XML('hello.glade') 
        
        
# 抓 glade 檔案裡面的 id="hello"
        
self.window = self.wTree.get_widget("hello")
        
# 如果有抓到這個物件
        
if (self.window):
            
# 關閉視窗時,執行 gtk.main_quit (其實就是把 GUI 關掉)
            
self.window.connect("destroy", gtk.main_quit)
            
            
# 就是少了這個害我畫面都出不來!
            
self.window.show()

if __name__ == "__main__":
    
hwg = HellowWorld()
    
gtk.main()



這是hello.glade,可以自己用glade3拉拉看
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.3 on Thu Nov 20 00:42:25 2008 -->
<glade-interface>
  
<widget class="GtkWindow" id="hello">
    
<child>
      
<widget class="GtkLabel" id="lab1">
        
<property name="visible">True</property>
        
<property name="label" translatable="yes">hello</property>
      
</widget>
    
</child>
  
</widget>
</glade-interface>

2008年11月18日 星期二

安裝 PyGtk 與其他相關套件

本來我是打算挑選 wxPython 做為 Python 語言的主力 GUI 工具,原因我已經忘了 ... 在沒有這個網誌之前就綜合網路上意見所決定的。

但還沒有開始研究 wxPython ,就突然因為工作關係必須開始學習 Gtk 了。雖然我已經忘記為什麼當初決定使用 wxPython ,但隱約記得 Gtk 給我的感覺並不好,但不是在開發階段,而是安裝階段 ...

不過不管怎樣,現在回頭來看 Gtk ,似乎感覺也是不賴的,當然我並沒有能力評斷兩種工具撰寫 code 的優劣,畢竟我只有用這兩種工具寫過小量的例子。





這邊做一些網上找回來的紀錄,都還只是網路上的片段句子,有空再回來証實並整理。


PyOpenGL 的安裝必須依靠 setuptools ,可以參考這個網站。
http://www.ibm.com/developerworks/cn/linux/l-cppeak3.html


PyOpenGL 的官方網站就在這囉 ...
http://pyopengl.sourceforge.net/


要讓 pyGtk 可以使用 OpenGL 的一些函式,就必須安裝 PyGtkGlExt (Python Gtk GL Extension?)才可以。底下這個官網也有 all-in-one ,可以一口氣安裝 PyGtk 、 PyOpenGL ... etc
http://www.k-3d.org/gtkglext/Main_Page


主角之一的 Gtk 官方網站
http://www.gtk.org/


其實真正要動只要安裝這個應該就可以動了 ... (可以在 Python 中 import gtk)
Gtk runtime++


glade 是可以為 Gtk 產生拖拉點放碼的工具,已經附在gtk-dev-2.12.9-win32-2.exe,但要更改一下它的捷徑 ... 要指向 C:\GTK\bin\glade-3.exe (不知道為什麼他原本是C:\GTK\bin\glade-2.exe)



這是可以參考的網站之一
http://vpoohtw.blogspot.com/2008/05/pygtk.html


至於 pyWin32 是可以利用 python 與 windows 的一些應用程式(如 outlook)溝通的套件。


pyCairo 是可以讓 Gtk 擁有比較炫的圖案


ATK(Accessibility Tool Kit) 讓程式能提供更友善、更易於操作的介面。


Pango 則是處理多國語言的好幫手 ...


這是一個 C 的 Gtk 的教學網站,有踩地雷的實例
http://debian.linux.org.tw/~kevpeng/




先這樣,有空再來整理 ...

2008年11月16日 星期日

破解無名小站

我其實可以理解想破解無名小站的心態,但我卻無法理解那些明明知道無名小站可以破解,卻還是要把裸照放在網路上的人 ...

身為一般使用者,想破解相簿自然是想看一些好康的,又或是與人結怨,想破解相簿讓他難堪,這是很容易理解的。

而身為技術人,骨子裡多少都會有一些不安分因子,總是會想要嘗試看看自己是否有辦法破解。

沒想到的是,無名小站的防護機制竟是如此的薄弱,連我這種菜鳥都可以輕易的破解自己跟朋友的相簿(朋友的相簿當然是經過他同意的) ...

奉勸大家真的不要再把隱私照放在網路上了!

2008年11月13日 星期四

用 Tcl 實作發送 Snmptrap

其實我還不是很熟 Snmptrap 啦 ... 只是在網路上看到了一篇 PPT ,就試著實作看看。

參考的網址如下:
http://www.chu.edu.tw/~hsiang/91_Class/NM2.ppt


符合 BER 格式的封包內容像這樣 ... (這算是補充 PTT 沒有的部份)



底下就是一份實作的範例

snmptrap.tcl
# Snmptrap 封包內容共三段
# Version + Community + Data(SNMP Protocol Data Unit (SNMP PDU))

# ------------------------------------
#            |Type
# ------------------------------------
# Version    |INTEGER {version-1(0)}
# Community  |OCTET STRING
# Data       |ANY (Sequence)
# ------------------------------------


# 其中 Data 又分為兩段
# PDU Header + PDU Data


# PDU Header 又分五段
# Enterprise + Agent address + Generic trap type + Specific trap code + Time stamp

# Enterprise—Identifies the type of managed object that generates the trap.
# Agent address—Provides the address of the managed object that generates the trap.
# Generic trap type—Indicates one of a number of generic trap types.
# Specific trap code—Indicates one of a number of specific trap codes.
# Time stamp—Provides the amount of time that has elapsed between the last network reinitialization and generation of the trap.

# ------------------------------------
#                       |Type
# ------------------------------------
# Enterprise            |ObjectIdentifier
# Agent address         |Hex
# Generic trap type     |INTEGER
# Specific trap code    |INTEGER
# Time stamp            |IntegerOrEnum
# ------------------------------------



# PDU Data 為一份序列(Sequence),序列內容可以包含一個以上的序列,結構如下
# [[OID + Value][OID + Value][OID + Value] ... [OID + Value]]



# ------------------------
# For demo send trap ...

# ----------------------
# import package
# ----------------------


package require asn
package require udp
package require ip


# -------------------------
# utility procedures
# -------------------------

# Figure out what this machine's IP address is.
# Refernce http:
//wiki.tcl.tk/3015 to rewrite this proc
proc myip {} {
    
set myip "127.0.0.1"
    
switch $::tcl_platform(platform) {
        
unix {
            
set buffer [exec /sbin/ifconfig]
            
set scan "inet addr:"
            
foreach line [split $buffer \n] {
                
if ![regexp $scan $line] continue
                
set s [expr [string first $scan $line 0] + [string length $scan]]
                
set f [expr [string first " " $line $s] - 1]
                
set addr [string range $line $s $f]
                
if { $addr != "127.0.0.1" } {
                    
set myip $addr
                    
break
                
}
            
}
        
}
        
windows {
            
catch { exec ipconfig } data
            
set buffer [split $data \n]
            
foreach line $buffer {
                   
if [regexp -nocase {IP Address} $line] {
                    
set myip [string trim [lindex [split $line :] end]]
                    
break
                
}
            
}
        
}
    
}
    
return $myip
}

proc myHexIP {} {
    
return [string range [ip::toHex [myip]] 2 end]
}


proc send_trap {args} {
    
# ---------------------
    # Configuration
    # ---------------------

    
# send trap to ... ?
    set server 127.0.0.1
    
set port 162

    
# 0 | 1
    set version 0

    
# public | password
    set community public

    
# 1.3.6.1.4.1.23041
    set enterprise "1 3 6 1 4 1 23041"

    
set agent_address [myHexIP]

    
set generic_trap_type 6

    
set specific_trap_code 0

    
# --------------------------------
    # start for encoding

    
set timestamp [clock second]


    
# Version
    set packet [asn::asnInteger $version]

    
# Version + Community
    append packet [asn::asnOctetString $community]

    
# PDU Header = Enterprise + Agent address + Generic trap type + Specific trap code + Time stamp
    set PDU_Header [asn::asnObjectIdentifier $enterprise]
    
append PDU_Header [binary format H* "4004$agent_address"]
    
append PDU_Header [asn::asnInteger $generic_trap_type]
    
append PDU_Header [asn::asnInteger $specific_trap_code]
    
append PDU_Header [asn::asnIntegerOrEnum 43 [expr ([clock seconds] - $timestamp) * 100]]

    
# PDU Data = [[OID + Value][OID + Value][OID + Value] ... [OID + Value]]
    set PDU_Data ""

    
foreach {OID value} $args {
        
set sequence [asn::asnObjectIdentifier $OID]
        
append sequence [asn::asnOctetString [encoding convertto $value]]
        
        
# 將 OID + Value 編成一個序列
        set sequence [asn::asnSequence $sequence]
        
        
# 放入 PDU_Data 主序列中
        append PDU_Data $sequence
    
}

    
# 把 PDU_Data 正式編成一個序列
    set PDU_Data [asn::asnSequence $PDU_Data]


    
# SNMP PDU = PDU Header + PDU Data
    set SNMP_PDU [format {%s%s} $PDU_Header $PDU_Data]

    
# OCTET STRING (0x04)
    set SNMP_PDU [asn::asnChoiceConstr 4 $SNMP_PDU]

    
# Version + Community + Data(SNMP Protocol Data Unit (SNMP PDU))
    append packet $SNMP_PDU

    
# 把 packet 正式編成一個序列
    set packet [asn::asnSequence $packet]




    
# 發送 trap / udp
    set s [udp_open]
    
fconfigure $s -blocking 0 -remote [list $server $port] -translation binary -encoding binary
    
puts -nonewline $s $packet
    
flush $s
    
close $s
}


接下來只要利用 send_trap 這個 proc 並傳兩個參數(OID、value),就可以打開接收器看成果了!

2008年11月11日 星期二

Ruby 的 Class

Ruby 非常的靈活,以下的範例可以輕鬆添加 Fixnum (應該像是其他語言的 int 類別)這個類別的功能


test1.rb
# reference : Beginning Ruby From Novice to Professional

# 讓我們在 Fixnum 這個類別中添加一些功能 ...
class Fixnum
    
def sec
        
self
    
end
    
    
def min
        
self * 60
    
end
    
    
def hour
        
self.min * 60
    
end
    
    
def day
        
self.hour * 24
    
end
end

puts "這是 1 這個物件的類別 = #{1.class}"
puts "1.sec  = #{1.sec}"
puts "1.min  = #{1.min}"
puts "1.hour = #{1.hour}"
puts "1.day  = #{1.day}"




test1.rb的output會像這樣
這是 1 這個物件的類別 = Fixnum
1.sec = 1
1.min = 60
1.hour = 3600
1.day = 86400



可想而知 Ruby 的生產速度定是非常優秀的了

Ruby

其實不管從哪個層面來看,我都是個不合格的 Programmer ... 在我的觀念中,一個 Programmer 要會的基本語言就是 C ,但我卻只會 C 的皮毛而已。

第一個學習的語言就是腳本語言,這讓我很難回頭靜下心來學習 C ,我一直都是個目標導向的人,因此都是需要什麼才學習什麼,而這個原因幾乎也就是腳本語言誕生的目的 ...

我想大概哪天需要寫高效率的東西才會讓我靜下心好好研究 C 的奧妙吧 ...

離題了,標題是 Ruby ,會研究起 Ruby 是因為想多了解幾種腳本語言 ... 好吧,其實有很大原因是因為很好奇 Python 與 Ruby 的戰爭中,那些神人們所說論點,讓我想知道這兩種語言在根本上的差異。

因此 Ruby 也是我日後會嘗試接觸的語言之一了!

Ruby 與 Python

Ruby 與 Python 的戰爭我想是永無止息的一天了 ...

對我這個菜鳥來說,其實我根本不知道兩者都優劣在哪,網路上充斥著似乎兩種語言都精通的高手們(還有精通超過五種語言的高手呢),總是可以一直斥責對方,真神人境界也 ...

不知道何年何月何日我才可以有資格評斷兩種以上的語言呢 ...

目前台灣在網路上擁戴 Python 與 Ruby 的,我感覺就好像台灣政治的藍與綠,在氣質有根本上的不同 ...

藍 - Python
綠 - Ruby


說不定做個調查,還真的是如此呢!

不過常常看到某方的擁護者提出一個觀點-「寫程式是因人而異,所以那不是我們程式語言的錯」

這個論點其實是非常有問題的,工具的使用當然是因人而異,但卻不影響這個工具的客觀立場。

自行車給選手級的人騎著,當然是有機會可以超越機車,不過如果要環島一周,是那個工具比較優秀呢?

2008年11月6日 星期四

object & return

Python 的 class 功能真的比我想像中的強大多了 ...

這是一個範例,它定義了 object 各種需求的 return function
class a:
    
def __int__(self):
        
return 123456789
    
    
def __str__(self):
        
return 'this is a string'
    
    
def __unicode__(self):
        
return 'unicode here'



使用起來會像這樣
>>> s = a()
>>> int(s)
123456789
>>> str(s)
'this is a string'
>>> unicode(s)
u'unicode here'



可以應用在蠻多場合的!

2008年11月5日 星期三

class處理未宣告的method

class 有一個很神奇的 method,只要你在 class 中有宣告 def __getattr__(self, name),它便會把所有無法處理的優先丟給它處理。


這是一個範例
class controlMethod:
    
def otherMethod(self, name):
        
def method(*args, **kwargs):
            
print name, args, kwargs
        
return method
    
    
def __getattr__(self, name):
        
return self.otherMethod(name)
    
    
def hello(self):
        
print 'hello world'




使用起來會像這樣...
>>> c = controlMethod()
>>> c.hello()
hello world
>>> c.nono(1,2,a='die')
nono (1,2) {'a': 'die'}




在不同的應用上,也可以這樣設計
def method(*args, **kwargs):
    
print args, kwargs

class controlMethod:
    
def __getattr__(self, name):
        
return method
    
    
def hello(self):
        
print 'hello world'

Django的escape

由於 escape 通常都會大量的使用,因此在Django 1.0 的 template 中,已經不需要設置 filter escape 了,因為它已經是預設值了

所以又多了一個 on/off 功能..

這樣才會停止 escape 的功能
{% autoescape off %}
    {{ variable }}
{% endautoescape %}


當然也可以這樣使用,variable1 將會停用 escape 功能,variable2 就啟用 escape 功能
{% autoescape off %}
    {{ variable1 }}
    {% autoescape on %}
        {{ variable2 }}
    {% endautoescape %}
{% endautoescape %}


這樣子也會啟用
{% autoescape off %}
    {{ variable|escape }}
{% endautoescape %}