高見龍

iOS app/Ruby/Rails Developer & Instructor, 喜愛非主流的新玩具 :)

Method

為什麼要寫method?

程式碼就這樣一行一行的寫不好嗎? 當你的程式碼超過一定的行數的時候,一行一行的寫就不會是個好的寫法。通常我們會用一個抽象的名詞,來把一群連續或複合的動作給包在一起,這樣一來程式碼變得有系統了,心情也會變得比較好,重點是,會寫method,就容易會有種變成高手的錯覺!

雖然這也許是玩笑話,但把程式碼整理到method裡,程式碼會變得比較好維護,而且也更容易可以重複使用。

定義

method定義
1
2
3
4
5
6
7
8
def calc_method(a, b = 1):
  print a * b

def args_method(*args):
  print args

def kwargs_method(**kwargs):
  print kwargs

第1行的calc_method比較容易懂,這個method會接收2個參數,其中一個還是有預設值的;第4行的args_method後面的參數加了一顆*,表示傳進去的參數args會被集中成一個Tuple;而第7行的kwargs_method則會把傳進去的參數kwargs集中成一個Dictionary。

pass!! 什麼都不做..?

前面提到Python的程式是靠縮排來區分code block的,不過如果我們寫了一個method,但裡面目前還沒想到要寫什麼,或是在if..else..的判斷裡面暫時還沒想到要寫什麼內容,如果就這樣空的不理它是不行的,這時候你就需要pass這個什麼事都不做的東西,像這樣:

1
2
def do_something():
  pass

或是像這樣:

1
2
3
4
if age >= 18:
  pass
else:
  print "kid, go back to school!"

這個pass的用途,就是只放個包包佔位置而已,其它什麼事都不做。也許你會覺得很不習慣,不過這個應該只有像在Python這種依賴縮排的程式語言才看得到的特色(?)吧。

呼叫/使用

呼叫/使用
1
2
3
4
5
6
calc_method(4)
calc_method(4, 10)
calc_method(b = 10, a = 2)

args_method(1, 2, 3)
kwargs_method(name = "eddie", age = 20)

Python的method呼叫是透過小括號(),並且可以在裡面傳參數進去,不過Python的參數還滿自由的,不一定要照著順序傳進去,像是上面這段程式碼的第3行,只要知道變數名稱,用這種方式傳也是行得通的。

回傳值

每個method執行結束,可以使用return關鍵字來指定要回傳的值,如果沒有特別指定,則回傳值是None(相當於在別的程式語言的NullNil)。所以這段程式碼的的回傳值:

1
2
3
4
def calc_method(a, b = 1):
  print a * b

print calc_method(10)

因為calc_method最後並沒明確的指示要回傳什麼值,所以上面這段程式碼的執行結果,會得到在calc_method裡印出的結果10,以及用print把回傳值None給印出來。

Lambda? 黏巴達?

Lambda
1
2
my_profile = lambda user_name, age : "%s is %i years old" % (user_name, age)
print my_profile("eddie", 30)

lambda其實就是一種匿名(anonymous)的method,它不用像一般method使用def來事先定義好。

Method Decorator

decorator的意思簡單的說,就是用某個method把你原來的method給包起來,也就是你在執行內層method之前,會先執行外層的method。這個在Python或Django的程式碼還滿常見的,主要有兩種方式來實作:

第一種是使用method來做decorator:

method decorator
1
2
3
4
5
6
7
8
9
10
11
def my_deco(func_name):
  print "Hello, this is method decorator"
  def wrapper():
    return func_name
  return wrapper

@my_deco
def real_method():
  print "This is real method"

real_method()

另一種是使用類別來做decorator:

method decorator
1
2
3
4
5
6
7
8
9
10
11
12
13
class Deco(object):
  def __init__(self, func_name):
    self.func_name = func_name

  def __call__(self, *args):
    print "This is a decorator class"
    return self.func_name(*args)

@Deco
def real_method():
  print "This is real method"

real_method()

接下來,我們來看看在Python裡面的一些基本的資料型態.. 數字!

邏輯及流程控制

變數

在開始講流程控制之前,要先來看一下在Python的變數。

Pytho的變數有幾項特點以及有趣的使用:

  • 不用宣告,可以直接用 x = “abc”
  • 變數名稱沒有型態
  • x, y, z = 1, 2, 3 可一口氣指定多個變數
  • x, y = y, x 把x跟y的值對調
  • x, y, z = “abc” 會得到x = “a”, y = “b”, z = “c”
  • x = y = z = “abc” x、y、z都是"abc"

命名規範

  1. 最好取有意義且相關的
  2. 開頭只能以底線或英文字母
  3. 小心保留字

保留字:

and as assert break class continue def
del elif else except exec finally for
from global if import in is lambda
not or pass print raise return try
while with yield

如果這樣,那就這樣,不然就那樣.. 的if-else

所謂的邏輯控制,說穿了大概就是「如果下雨,就去吃麥當勞,不然就去吃肯德雞」之類的敘述罷了。如果我們把這段語法改寫成程式碼的話:

1
2
3
4
5
6
weather = "sunny"

if weather == 'rainy':
  print "go to M"
else:
  print "go to KFC"

如果你曾經學過別的程式語言,例如C/C++/PHP,你可能一下子看到這樣的程式碼會不太習慣。Python的code block不需要大括號,只要用整齊的縮排就可以了。至於你是要縮排2格空白、4格空白都可以,只要排整齊就好了。另外,每行的行末也不需要分號做為結束。

Python的變數不需要特別宣告,在做邏輯判斷的時候,如果不會影響語意的話,也是不需要小括號的。假設我們原來這段程式碼改用C-like的程式碼來改寫的話,可能會長得像這樣:

1
2
3
4
5
6
7
var weather:String = "sunny";

if (weather == "rainy"){
  print("go to M");
}else{
  print("go to KFC");
}

上面這段程式碼只是舉例,不一定完全正確。不過要表達一樣的意思,用Python就是可以讓你的程式碼變得簡單很多,至少你可以少敲好幾下鍵盤,也因為Python的程式碼強制一定要縮排排整齊,所以你也不用擔心程式碼風格會差很多的問題(當然有的人就是喜歡用奇技淫巧..硬是要寫得跟別人不同的也大有人在)。

if..else..,那當然也要來一下elseif之類的語法,不過Python的elseif是用elif

1
2
3
4
5
6
7
8
9
10
weather = "sunny"

if weather == 'rainy':
  print "M"

elif weather == 'not good':
  print "Stay at home"

else:
  print "KFC"

switch?

你知道當程式的判斷開始越來越多的時候,學校老師或是教課書上就會教我們用switch之類的語法來處理,不過,你可能會很訝異,Python沒有swtich之類的語法的,它就是用一大串的if..elif..else..來處理。

不優美嗎? 我覺得還好。反正Python程式碼的縮排很清楚,看起來也不會多混亂 :)

註解

Python的註解有兩種,單行註解跟多行註解。單行的這樣用:

1
# this is comment in python

多行的這樣用

1
2
3
4
5
"""
this is comment
this is comment, too!
many comment..
"""

中文字..會出現錯誤!!

如果你的檔案裡有用到非英文字元的話,請在檔案最前面加上一行:

# encoding: utf-8

這樣你的程式執行起來才不會跳出SyntaxError,誰叫電腦跟程式語言不是中國人發明的..

輸入/輸出

這個我們在寫一些console的應用程式的時候常會用到,前面我們已經用過print了,不過接下來我們來試著做個可以跟使用者互動的簡單小程式:

1
2
3
4
5
6
print "Hello, how old are you?"
age = raw_input()
if age >= 18:
  print "You're an Adult already!"
else:
  print "kid, go back to school!"

這其實也是個沒什麼實戰用途的程式碼範例,也沒有很嚴格的檢查輸入值的範圍,不過可以從這邊看到在Python的輸入/輸出大概是怎麼處理的。另外一樣在處理輸入的,還有兩個稍微要提的,分別是raw_inputget_pass模組。也許你會好奇inputraw_input的差別? 比較明顯的差別是在於數字的處理,如果你輸入20+3,你會得到23,但如果用的是raw_input的話,則是得到20+3這個字串。

不管是input或是raw_input,我們在輸入的過程中都會被旁邊的人看光光,如果你不想你在輸入密碼的時候全部都秀在畫面上,你可以使用get_pass這個內建的模組。我們直接在shell裡試試看:

>>> import getpass
>>> getpass.getuser()
>>> your_pw = getpass.getpass("please input your password: ")
please input your password:

這樣你打的字就應該不會被看到了。

接下來,我們要來把這些程式碼包成method(方法)..

如果你是使用Windows作業系統的話..

在Windows安裝Python很難嗎?

就安裝的話,一點都不難,因為Python已經有幫Windows做好安裝檔了,檔案下載回來之後點一點、下一步的按鈕按一按差不多就搞定了。

其實在Windows上寫Python,Python本身沒什麼問題,倒是環境比較痛苦。特別是之後的Django,它的懶人安裝包(Instant Django)專案也已經消失了,在Windows上練習寫Django的麻煩度就又增加了..

有比較完美的解決方法嗎?

最完美的解決方法就是 - 不要用Windows,不過我想那對正在用Windows的人來還滿困難的。

如果你因為工作或是其它因素不得不用它,那也許可以考慮安裝雙系統,或是像VirtualBox在Windows上模擬Linux的作業環境。我之前試過VirtualBox的這個解決方案,其實還滿完美的,之前在中研院OpenFoundry的工作坊講課的時候就是用它搭配Ubuntu,還滿ok的,但可惜就是速度會慢了點,遇到硬體設備比較差的電腦跑起來會有點辛苦。

如果你不想重灌或安裝VirtualBox,我自己試了一下,大概安裝Cygwin是比較簡單的解決方法了。

Cygwin的官網一進去就看到"Get that Linux feeling - on Windows!“,雖然離真正的Linux還是有點距離,但光是這個feeling,大概就可以讓我們在上面練習Python跟Django了。

在安裝Cygwin的過程中,請順便勾選Pythonwget這兩個工具選項,在安裝Cygwin的過程中也會一併把這些工具一起裝進Cygwin的系統裡。

它所有的軟體都會安裝在Cygwin自己的資料夾裡,所以如果你不要用的話,整個資料夾砍掉就行了。

安裝完Cygwin之後,因為我們可能從Windows貼一些指令到Cygwin,如果你發現你的Cygwin沒辦法接受滑鼠右鍵貼上的話,請改一下視窗的設定:

在視窗的上面按一下滑鼠右鍵,選擇「內容」:

image

把「快速編輯模式」打勾:

image

這樣就搞定了!

編輯器呢?

雖然說Python程式碼用記事本就可以寫了沒錯,但因為記事本功能太陽春,通常那是最不得已才會開它起來改程式。我想現在文字編輯器的牌子不少,每款軟體用起來的手感也不太一樣,大家可以多比較看看哪些編輯器。如果你懶得比較,那就直接抓Notepad++來用吧,至少它該有的程式碼顏色功能都有了。

安裝Python

不管你用的Linux/FreeBSD/MacOS/Windows..etc,目前Python均有實作品,請至http://python.org/getit/找到適合的平台並下載安裝。

不過,我不得小小抱怨一下,Python在Windows上實在是不怎麼友善,包括我們之後要講的Django,原本也有給Windows的懶人安裝包(Instant Django),但專案似乎也斷頭了。不過也不是沒有解決方法,如果只是要在Windows做練習的話,可參考下一章

如果你安裝完成,請打開你的終端機視窗,輸入python就可以進入interactive shell來試玩一下:

> python
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "hello python"
'hello python'
>>> 1 + 2
3

在這個shell裡面,你可以很容易的就測試一些簡單的程式碼,看看執行結果是不是跟你想像的是一樣的。有趣的是,如果你在shell裡輸入import this的話:

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

你可以看到Tim Peters寫的The Zen of Python,內文大概說明了Python世界的設計哲學。至於import是做什麼用的,我們在後面的單元會再做說明。

除了shell之外,我們更常把程式碼儲存成一個檔案,附檔名是.py,例如我們把下面這段很簡單的程式碼:

1
2
#!/usr/bin/python
print "Hello, Python"

用任何文字編輯器打完之後,存檔為hello.py,然後回到終端機視窗,輸入python hello.py

> python test.py
Hello, Python

每種程式語言一定都要不免俗的來一下Hello World打個招呼的,如果在Java,你可能為了要輸出一行簡單的字,還得寫個類別或方法才行,在Python,只要一行print就搞定了,相當簡單吧 :)

其實老是Hello World也沒什麼意義,接下來我們來看一點稍微複雜一點的..

Python簡介

What is Python?

Python的老爸是,Guido van Rossum,聽說是他在1989年的時候的某個聖誕節無聊,然後就設計出這套程式語言,1991年放出來給大家用,到目前已經有將近20年的歷史了。

目前主流的版本是2.x跟3.x系列,最新的版本目前分別是2.7.2版及3.2.2版,但2.x跟3.x有不少地方是不相容的,各位在使用時還請多留意。

設計哲學

the Zen of Python裡提到了Python的設計哲學:

There should be one-- and preferably only one --obvious way to do it.

這與其它程式語言例如Perl的"There is more than one way to do it"是完全不同的。

What can Python do?

Python是一種物件導向的語言,雖然它被歸類到scripting language一族,但它能做的事情跟一般的程式語言一樣,從數學運算、系統管理到網站開發,它都做得來的,而且都還做得不錯。

有人會覺得嫌Python很慢,老實說,我是不覺得慢到哪裡去。當然拿它跟編譯型的程式語言比當然不公平,不過也就是因為它不用編譯,而且語法很好學好寫,開發速度相對的會比編譯型的語言要來得高。

Who is using Python?

  • Google
  • Youtube
  • NASA
  • ..and ME!

Why Python?

每種程式語言都有它的優缺點,以下是我個人覺得我喜歡Python的一些特點:

程式碼強制縮排

在Python寫程式,程式碼強制一定要縮排,長得像這樣:

say hello
1
2
3
def say_hello():
  print "Hello Python"
  print "Hello again!"

像這樣,不管你是要用tab或空白(space)都可以,要縮2格或4格都ok,只要對齊就行了。只要程式碼沒有對齊,在執行的時候就會直接出現IndentationError的錯誤訊息而無法繼續執行。

也許有些人不喜歡這種被強制規定的感覺,不過我個人還滿喜歡的。在別的程式語言,有的人喜歡把大括號放在最後面,有人喜歡把大括號放下一行,像這樣:

大括號的位置
1
2
3
4
5
6
7
8
function type1(){
  // 把大括號放最後面
}

function type2()
{
  // 把大括號放下一行
}

這沒有誰好誰壞的問題,不過這個在Python就比較不會有這樣的困擾,也因為如此,即使你是接手別人的案子,基本上程式碼的長相也不會差太多。

而且我真的遇過程式碼不縮排或亂縮排的工程師..

支援多個平台

目前幾乎所有比較主流的平台上面都有支援了,也就是說你在Linux底下寫的程式,搬到Windows上也能執行。(當然前提是沒有用到一些系統特定的模組或method)

免費取得

不僅不用錢,而且連Python的原始碼都可以讓你帶回家研究。

開發工具易取得

其實寫Python不用什麼特別的開發工具,基本上只要是一般的文字編輯器就可以了。也有一些像PyDev這種為Python量身打造的IDE(Integrated Development Environment)也不錯用,不過我個人偏好純文字編輯器,例如Vi,至少開啟速度快,而且搭配一些好用的外掛,該有的功能都差不多該有了。

其它

電腦程式語言幾乎都是外國人的世界,你有想過用中文可以寫程式嗎? 有個叫做周蟒的專案做到了。這是用中文寫出來的Python程式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env zhpy
# 檔名: if.py
數字 = 23
猜測 = 整數(輸入('輸入一個數字: '))
如果 猜測 == 數字:
    印出 '恭喜, 你猜對了.' # 一個新區塊的開始
    印出 '(但沒有獎品喔!)' # 新區塊的結束
假使 猜測 < 數字:
    印出 '錯了, 數字再大一點.' # 另一個區塊
    # 你可以在區塊中做任何想做的事 ...
否則:
    印出 '錯了, 數字再小一點.'
    # 只有在猜測 > 數字 的情況下才會跑到這個區塊來
印出 '結束'
# 最後一行語句和"如果..假使..否則"語句是無關的,
# 因為最後的'印出'這行在主區塊中出現,所以這行永遠會被執行.

好寫嗎? 這見人見智了,不過挺有趣的,有興趣的朋友可以玩看看 :)