所謂工欲善其事,必先利其器。
選擇 Python 的理由又是什麼?
那我們得先從語言的特性及優缺點來探討。
Python 不是爬蟲類,跟 Johnson 也沒關係。
它,是個直譯式、交互式、動態型別、物件導向的程式語言。
那這些特性是什麼意思呢?
直譯式語言 (Interpreted language)
首先我們要知道,Python 是一個 High-level programming language,以人類的日常語言為基礎的一種程式語言,言下之意,你在 Editor 或 IDE 上寫的程式碼都是給人看的。所以當我們要讓電腦去執行程式碼時,必須將這些程式編譯成電腦看得懂的語言,而直譯式就是我們編譯程式碼的方式。
直譯式怎麼編譯呢?就是編譯一行,執行一行。
而另一種跟直譯式相反的則稱為編譯式語言 (Compiled language),編譯式語言是全部編譯完後才會去執行。
交互式程式設計 (Interactive programming)
因為直譯器的好處是每次程式更新後它不需要重新編譯整個程式。Jupyter 就是 Python 的交互式程式設計的介面,而 VSCode 本身也有支援這種介面,可以參考這邊的教學使用。
如圖所示,程式可以一行一行的執行,假如遇到前置處理的資料很龐大的時候,不用從頭跑一遍,可以只執行後面修改的部分,這樣一來就能省下不少時間!
動態型別(Dynamic typing)
讓同一個變數在執行時能被賦予不同型別的值。
dynamic = 5
dynamic = "Hello world"
print(dynamic)
輸出結果:
但同樣的作法在 Java 中就會出現錯誤(靜態型別)
public class Main {
public static void main(String[] args) {
int dynamic;
dynamic = 5;
dynamic = "Hello world";
System.out.println(dynamic);
}
}
輸出結果:
物件導向程式設計(Object-oriented programming)
以下是物件導向的簡單概述。
所謂物件導向,就是只能透過物件本身所提供的介面 (Interface) 來存取 (Access) 物件內部的屬性或者方法。可以分成以下:
覆寫(Overriding): 覆蓋父類別原本的方法,在子類別中宣告與父類別相同的方法即可覆蓋。
class A:
def foo(self):
print("A")
class B(A): # 繼承
def foo(self): # Overriding
print("B")
多載(Overloading): 在相同類別中,名稱相同,但是參數個數不同,或是參數型態不同,進而執行不同的行為。
這邊先以 Java 作為範例:
// Java Overloading Example
public class A {
public int calArea(int x, int y){
return (x + y);
}
public double calArea(double x, double y){
// 同名稱,不同型態
return (x + y);
}
public int calArea(int x, int y, int z){
// 同名稱,不同參數個數
return (x + y + z);
}
}
那 Python 呢?
# Python Overloading Example
class A:
def foo(self):
print("A")
def foo(self, number): # Overloading
print(number)
a = A()
a.foo()
我們試著呼叫第一個沒有任何參數的 function 看看:
可以發現我們呼叫的 foo function 被覆寫掉了!為什麼!?
因為 Python 是動態型別的語言,可以接受任何型態的參數,所以對 Python 來說 Overloading 是不太必要的,裡面寫個 if-else 就能解決了。
難道 Python 就不能做"正規的" Overloading 嗎?
可以!但實作上較為複雜,且需要對 Decorator 有基本的了解。想知道更多可以參閱此文章。