高見龍

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

數字

沒有上限?

在Python,數字基本上是沒有上限的。也不是說沒有沒有上限,就用到電腦記憶體用完為止。有些程式語言的數字的值都有一個限制,超過就會發生溢位(overflow)。什麼是溢位? 就像你車子的里程表,假設全部有6個位數,也就是最大顯示是999999,但只要超過這個數字就會從000000開始,在處理資料的時候,這通常不會是你想要的結果。而Python沒有這個問題,也就是因為這樣,Python可以拿來算很大的數字都是ok的。

數字裡面,只要有小數點就會被視為浮點數,而浮點數會有誤差,例如:

1
print 0.1 + 0.1 + 0.1 - 0.3

算出來的結果應該跟我們人類的腦袋不太一樣。如果你有這方面的需求,可以藉助Decimal模組的幫忙:

>>> from decimal import *
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')

這樣算出來應該就會是你要的了。

四則運算

基本上跟我們在小學時候學的差不多,就加+、減-、乘*、除/,先乘除後加減,如果遇到括號要先處理。這些都差不多,不過"除法"比較不一樣一點,如果除數跟被除數都是整數的話,那算出來的結果就會是整數,例如:

print 10/3     # 3

如果你在除數或被除數其中一個加上小數點,讓它變成浮點數型態的話,算出來就又不一樣了:

print 10.0/3   # 3.333333333

但如果你想要強迫進行整數除法的話,請使用//

print 10.0//3  # 3.0

次方則是使用**

print 2**3     # 8

型態轉換可使用int()float()complex()等方法來把原來的數字轉換成整數、浮點數以及複數型態。

再來,我們來看看Python的Boolean型態..

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也沒什麼意義,接下來我們來看一點稍微複雜一點的..