變數、物件型別與運算式


前言

經歷了上一堂課後,相信學員們對於程式設計的運作都有一些基本概念,也知道如何透過流程圖、文字敘述等方式拆解一個問題需求。接下來我們要來認識變數、物件型別與運算式。事實上,我們在上一堂課就已經使用了變數、物件型別與運算式在我們的隨堂練習和作業任務中,接著我們要更進一步去了解他們的背後原理。

Python 世界都是物件

在開始進一步學習前,我們需要先建立一個世界觀:Python 和一些程式語言不一樣的地方在於在 Python 世界裡每個東西都是物件(object)。

那什麼是物件(object)呢?事實上,物件就是程式語言與日常生活的一種對應,每個物件都具有屬性(attribute)和方法(method)。

  1. 屬性(attribute):從屬性中可以得到該物件的相關資訊
  2. 方法(method):可以針對該物件進行操作

感覺很抽象?舉例來說,真實世界裡的車子有顏色,品牌等屬性,還可以前進,後退來操作車子。所以你也可以在 Python 世界裡透過車子(Car)類別(class)來產生車子(car)物件實例(instance),而車子物件有車子品牌的屬性(attribute)和可以開車的方法(method)。

(圖片來源:0371techan

關於物件和類別的探討我們會在後面的課堂更深入的探討,目前我們只要先知道 Python 世界裡定義的東西都是物件,也有許多常用內建的物件可以讓你使用,這也是大家喜歡使用 Python 的原因,因為已經有很多內建好的物件方法可以去使用和呼叫,就不用自己再寫程式碼了!

例如:字串物件,當你宣告了 name = 'Jack'(用 '' 單引號括起來的我們稱之為字串),就是宣告了一個字串物件並貼上 name 這個名稱。此時我們就可以使用字串物件的方法來進行操作,例如使用 upper() 方法會複製字串物件內容值並轉成大寫後回傳(官方文件說明)。

你可以開啟 repl.it 並開新的 repl 選擇 Python,輸入以下指令,然後按 run 執行:

print('Jack'.upper())

# 結果出現 'JACK',其回傳字串物件轉成大寫的值

想知道物件有哪些內建函式可以使用,可以使用 dir() 列出相關物件資訊,可以看到除了 upper 外還有 lower 轉成小寫可以使用:

# 看起來有很多可以使用的物件方法,但這些都可以在文件中查詢到,用到再查詢就好
dir('Jack')
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

這時同學們就會問啦,內建語法這麼多怎麼記得住?事實上,我們並不需要全部記住所有語法,只要掌握住常用語法,剩下的就是在需要使用的時候會 google 查訊就好。但重要的是要知道如何查詢

例如我今天要使用 Python 內建去除字串空白的方法,我要如何查詢?

一種是直接 google 中文:Python 內建去除字串空白

另外一種是使用英文:python Remove white space

其中 stackoverflow 是全球最大的程式問答網站,github 則是全球最大的程式碼分享平台,很多時候我們可以透過上面網友的分享可以了解怎樣解決問題,以及該下什麼關鍵字去找答案。

Python 官方網站的文件查詢則是查詢語法使用的好幫手,就像字典一樣,當我們需要使用的時候就去查詢一下(右上角有搜尋框),文件會告訴你查詢語法的使用方法:

事實上,自學程式設計不僅僅是要學習如何撰寫程式,更重要的是如何透過自學程式設計的過程中學習和培養如何解決問題和跨領域自學的能力!

隨堂練習:將字串物件轉成小寫

請使用字串物件內建的方法:lower 將,名稱為 name 的字串物件值轉成小寫值印出:

將物件指派(assign)給變數

在 Python 程式語言的世界裡,使用 = 來連結變數名稱和對應的物件。這和數學的等於是不同的,之前我們提過 == 在 Python 的世界裡才是相等的意思。當給物件貼上名稱後我們就可以在稍候的程式使用到它。這時候你可能就會問,那變數和物件是存在電腦的哪個地方呢?答案是記憶體(memory)中。

圖片來源

一般程式檔是由上往下執行,變數就是讓我們可以暫存一些資料在記憶體中,方便我們接下來的程式碼可以使用

這裡特別要注意的是,Python 和一些程式語言比較不同的是,Python 的變數不是存實際的值,而是讓變數和物件連結在一起。你可以想成便條紙的概念,在上面寫上變數名稱 name 貼到 Jack 物件上(初始化變數),但 name 是可以撕下來貼到其他物件上例如:name = 'Tony',此時 name 就連結到的是 Tony(重新指派變數)。

在一些程式語言例如 C,變數就像是一個盒子,儲存實際複製的數值,但在 Python 世界都是物件,變數是儲存指到該物件的參考位置

# 可觀察兩者輸出差異
name = 'Jack'

print(id(name))

name = 'Tony'

print(id(name))

透過 id() Python 內建函式會回傳該物件在電腦中儲存的記憶體位置(參考官方文件)。

id(object)
Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

CPython implementation detail: This is the address of the object in memory.

在 Python 中給定變數值就像是把變數名稱這個便條紙貼到(指到)物件(存在某個記憶體位置上)上面:

重新給定變數值就好像把便利貼撕下來,貼到另外一個物件上面:

可以看到變數重新指定的底層儲存差異:

a = 3
b = 2

c = a + b
# 5

# 顯示變數指到物件的識別碼
id(a)
id(b)
id(c)

# 重新指派物件後識別碼改變
a = 1
id(a)

若是完整對應到實體的記憶體概念會是這樣:

其他有些程式語言會是存一份複製的實際值,所以你看到有些程式設計書籍會把變數比喻成存資料的盒子,就是這個意思(把 'Jack' 實際值放入變數盒子):

這邊對於初學者來說可能需要時間消化,不過沒關係,可以先記得一般程式是由上往下執行,變數就是讓我們可以暫存一些資料在電腦記憶體中,方便我們接下來的程式碼可以使用。

隨堂練習:使用變數

請試著執行以下程式:宣告一個變數 language 給定一個字串物件 'Java',並使用 id() 內建函式印出其記憶體位置,接著將 language 重新指到 'Python' 字串物件,請觀察兩者記憶體位置差異。

變數命名(naming)

Python 規定變數命名規則如下,在使用上盡量使用有意義的名稱(ex. raw_data,不要使用 a, b 等無意義命名):

  1. 變數名稱需要為英文字母開頭或是底線開頭(底線通常為私有變數命名使用,這部份先記得就好)
  2. 開頭首字之後可以是字母、數字或是底線
  3. 大小寫是屬於不同變數
  4. 通常變數會用小寫命名,不同單字使用底線連接(ex. chance_of_rainfall
  5. 變數中不能使用 .! 等符號
# 錯誤
123name

# 正確
_name_123
name

隨堂練習:變數命名抓錯

請指出哪些變數命名有問題?

物件型別

基本資料型別

  1. int 整數:指沒有小數的數字
  2. float 浮點數:有小數的數字
  3. bool 布林:代表真假值(True/False),進行條件判斷使用
  4. str 字串:由一個個字元(character)組成的字串
  5. NoneType 型別:None 代表沒有值的物件

我們可以使用 type() 這個 Python 內建函式確認變數型別:

# 使用 type() 內建函式確認變數型別
name = 'Jack'
# 變數型別 str
type(name)

型別轉換

若是你想將變數的值進行型別轉換的話,也可以使用下面函式進行型別轉換:

  1. int():轉成整數
  2. float():轉成浮點數
  3. str():轉成字串
# 4
int(4.56)

# 4.0
float(4)

# '1'
str(1)

隨堂練習:BMI 身高體重指數

請執行以下程式練習實際操作 weight / height 變數,請在 weight = 60 下面再重新宣告 weight = 70,印出 BMI 對應成果(注意 ** 為平方意思):

敘述(statement)與運算式(expression)

敘述(statement)和運算式(expression)兩者差異在於敘述沒有將結果給定給一個變數值:

# 敘述
1 + 2

# 運算式
sum = 1 + 2

運算子與運算元

運算子(operator,ex. +、-、/ 等)是操作運算式內運算元(operand)的符號(常見運算元為數值),常見使用情境為 Python 四則運算。遵守由左至右、括弧優先,先乘除後加減原則。亦即運算子優先順序和關聯性會決定作業的執行順序。

口訣:由左至右、括弧優先,先乘除後加減

x = 10
y = 2
z = 3
result = (x + y) * z + x * y

print(result)
# 56

若是希望累加操作,你也可以簡寫成:

sum = 0
# 等同於 sum = sum + 1,以下以此類推
sum += 1
sum -= 1
sum *= 1
sum /= 1
% 為取餘數
sum %= 1

隨堂練習:猜猜四則運算結果

猜猜看下面四則運算的運算結果為何?

總結

以上我們討論了變數、物件型別與運算式,讓你對於變數、物件、常見資料型別、運算式等基礎概念:

  1. Python 世界都是物件
  2. 將物件指派(assign)給變數
  3. 變數命名(naming)
  4. 敘述(statement)與運算式(expression)
  5. 運算子與運算元

特別要注意的是 Python 的世界都是物件,物件具備屬性及方法。變數的命名和行別的轉換也是非常重要的基礎觀念,務必自己動手練習看看。接下來我們會透過使用者的輸入輸出更進一步了解相關應用方式。



問題討論區
加入問題討論
作業任務區
提交作業任務