Think Python/變數、表示式和語句
值和型別
[edit | edit source]值是程式操作的基本事物之一,例如字母或數字。我們到目前為止見過的值包括1, 2,以及 'Hello, World!'。
這些值屬於不同的型別2是一個整數,而 'Hello, World!' 是一個字串,之所以稱為字串,是因為它包含一個字母“字串”。您可以(以及直譯器)透過它們是否包含在引號中來識別字符串。
print 語句也適用於整數。
>>> print (4)
4
如果您不確定某個值的型別,直譯器可以告訴您。
>>> type('Hello, World!')
<type 'str'>
>>> type(17)
<type 'int'>
不出所料,字串屬於型別str,而整數屬於型別int。不太明顯的是,帶小數點的數字屬於一種稱為float的型別,因為這些數字以一種稱為浮點數的格式表示。
>>> type(3.2)
<type 'float'>
那麼像 '17' 和 '3.2' 這樣的值呢?它們看起來像數字,但它們包含在像字串一樣的引號中。
>>> type('17')
<type 'str'>
>>> type('3.2')
<type 'str'>
它們是字串。
當您輸入一個大整數時,您可能會傾向於在三位數的組之間使用逗號,例如1,000,000。這在 Python 中不是一個合法的整數,但它是合法的
>>> print 1,000,000
1 0 0
嗯,這完全不是我們預期的!Python 將1,000,000解釋為一個以逗號分隔的整數序列,它以空格分隔的形式打印出來。
這是我們見過的第一個語義錯誤示例:程式碼在沒有產生錯誤訊息的情況下執行,但它並沒有做“正確”的事情。
變數
[edit | edit source]程式語言最強大的功能之一是能夠操作變數。變數是引用值的名稱。
賦值語句建立新的變數並賦予它們值
>>> message = 'And now for something completely different'
>>> n = 17
>>> pi = 3.1415926535897931
此示例進行了三個賦值。第一個將字串賦值給一個名為message的新變數;第二個將整數17賦值給n;第三個將 π 的(近似)值賦值給pi.
。在紙上表示變數的一種常見方法是寫下名稱,並用箭頭指向變數的值。這種圖被稱為狀態圖,因為它顯示了每個變數的狀態(將其視為變數的心態)。此圖顯示了上一個示例的結果
message
|
'And now for something completely different'
| |
n
|
17
| |
pi
|
3.1415926535897931
|
要顯示變數的值,可以使用 print 語句
>>> print n
17
>>> print pi
3.14159265359
變數的型別是它引用的值的型別。
>>> type(message)
<type 'str'>
>>> type(n)
<type 'int'>
>>> type(pi)
<type 'float'>
練習 1
[edit | edit source]如果您輸入一個以零開頭的整數,您可能會得到一個令人困惑的錯誤
>>> zipcode = 02492
^
SyntaxError: invalid token
其他數字似乎可以工作,但結果很奇怪
>>> zipcode = 02132
>>> print zipcode
1114
你能弄清楚發生了什麼事嗎?提示:列印值 01、010、0100 和 01000。
變數名和關鍵字
[edit | edit source]程式設計師通常會選擇對變數有意義的名稱——它們記錄了變數的使用目的。
變數名可以任意長。它們可以包含字母和數字,但必須以字母開頭。使用大寫字母是合法的,但最好以小寫字母開頭變數名(您將在後面看到原因)。
下劃線字元 (_) 可以出現在名稱中。它通常用於包含多個單詞的名稱,例如 my_name 或 airspeed_of_unladen_swallow。
如果您給變數一個非法名稱,您將得到一個語法錯誤
>>> 76trombones = 'big parade'
SyntaxError: invalid syntax
>>> more@ = 1000000
SyntaxError: invalid syntax
>>> class = 'Advanced Theoretical Zymurgy'
SyntaxError: invalid syntax
76trombones是非法的,因為它沒有以字母開頭。more@是非法的,因為它包含一個非法字元,@。但class?
有什麼問題呢?事實證明class是 Python 的關鍵字之一。直譯器使用關鍵字來識別程式的結構,它們不能用作變數名。
Python 有 31 個關鍵字
以及
|
del
|
from
|
not
|
while
|
as
|
elif
|
global
|
or
|
with
|
assert
|
else
|
if
|
pass
|
yield
|
break
|
except
|
import
|
print
| |
class
|
exec
|
in
|
raise
| |
continue
|
finally
|
is
|
return
| |
def
|
for
|
lambda
|
try
|
您可能需要將此列表隨時備用。如果直譯器抱怨您的變數名稱之一,而您不知道原因,請檢視它是否在此列表中。
如果您在瞭解 Python 的文字編輯器中編寫程式碼,您可能會發現它可以輕鬆地讓您發現此類關鍵字衝突,因為它以與普通變數不同的顏色顯示關鍵字。此功能稱為語法高亮,大多數程式設計師都認為它是必不可少的。本書為其示例程式碼使用語法高亮,因此在以下示例中
ok_variable = 42
yield = 42
您可以看到 yield 被識別為關鍵字,而不是普通變數,因為它被塗成綠色。
語句
[edit | edit source]語句是 Python 直譯器可以執行的程式碼單元。我們已經看到了兩種語句:print 和賦值。
當您在互動模式下鍵入語句時,直譯器會執行它並顯示結果(如果有)。
指令碼通常包含一系列語句。如果有多個語句,則結果將隨著語句執行而逐一齣現。
例如,指令碼
print 1
x = 2
print x
產生以下輸出
1
2
賦值語句不會產生輸出。
運算子和運算元
[edit | edit source]運算子是代表計算(如加法和乘法)的特殊符號。運算子應用到的值稱為運算元。
運算子+, -, *, /以及**執行加法、減法、乘法、除法和求冪,如以下示例所示
20+32 hour-1 hour*60+minute minute/60 5**2 (5+9)*(15-7)
在其他一些語言中,^ 用於求冪,但在 Python 中,它是一個稱為異或的按位運算子。我不會在本手冊中介紹按位運算子,但您可以在以下地址閱讀相關內容:wiki.python.org/moin/BitwiseOperators.
除法運算子可能不會按預期執行
>>> minute = 59
>>> minute/60
0
的值minute是 59,在傳統的算術運算中,59 除以 60 等於 0.98333,而不是 0。造成這種差異的原因是 Python 執行的是向下取整除法。[1]
當兩個運算元都是整數時,結果也是整數;向下取整除法會將小數部分截斷,因此在本例中,它向下取整為零。
如果運算元之一是浮點數,Python 將執行浮點數除法,結果為一個float:
>>> minute/60.0
0.98333333333333328
表示式
[edit | edit source]一個表示式是值、變數和運算子的組合。一個值本身被認為是一個表示式,變數也是,因此以下都是合法表示式(假設變數x已經被賦值了)
17
x
x + 17
如果你在互動模式下輸入一個表示式,直譯器會計算它並顯示結果
>>> 1 + 1
2
但在指令碼中,一個表示式本身不會做任何事情!這是初學者常犯的錯誤。
練習 2
[edit | edit source]在 Python 直譯器中輸入以下語句,看看它們做了什麼
5
x = 5
x + 1
現在將相同的語句放到指令碼中並執行它。輸出是什麼?透過將每個表示式轉換為 print 語句來修改指令碼,然後再次執行它。
運算順序
[edit | edit source]當一個表示式中出現多個運算子時,運算順序取決於優先順序規則。對於數學運算子,Python 遵循數學慣例。首字母縮略詞PEMDAS是記憶規則的一種有用方法
- Parentheses 具有最高優先順序,可用於強制表示式按您想要的順序計算。由於括號內的表示式首先計算,因此2 * (3-1)為 4,而(1+1)**(5-2)為 8。您也可以使用括號使表示式更易於閱讀,例如(minute * 100) / 60,即使它不改變結果。
- Exponentiation 具有次高優先順序,因此2**1+1為 3,而不是 4,並且3*1**3為 3,而不是 27。
- Multiplication 和 Division 具有相同的優先順序,高於 Addition 和 Subtraction,它們也具有相同的優先順序。所以2*3-1為 5,而不是 4,並且6+4/2為 8,而不是 5。
- 具有相同優先順序的運算子從左到右計算。因此在表示式degrees / 2 * pi中,除法首先發生,結果乘以pi。要除以 2 π,您可以重新排序運算元或使用括號。
字串操作
[edit | edit source]一般來說,您不能對字串執行數學運算,即使字串看起來像數字,因此以下操作是非法的
'2'-'1' 'eggs'/'easy' 'third'*'a charm'
the+運算子與字串一起使用,但它可能不會按預期執行:它執行串聯,這意味著將字串首尾相連。例如
first = 'throat'
second = 'warbler'
print first + second
該程式的輸出是throatwarbler.
the*運算子也適用於字串;它執行重複。例如,’Spam’*3是 'SpamSpamSpam'。如果運算元之一是字串,另一個必須是整數。
這種使用+以及*有意義,因為它與加法和乘法類似。就像4*3等同於4+4+4一樣,我們希望 'Spam'*3 與 'Spam'+'Spam'+'Spam' 相同,它確實相同。另一方面,字串串聯和重複與整數加法和乘法有一個顯著的區別。你能想到加法具有的而字串串聯不具有的屬性嗎?
註釋
[edit | edit source]隨著程式變得越來越大、越來越複雜,它們也越來越難讀。形式語言很密集,通常很難檢視一段程式碼並弄清楚它在做什麼,或者為什麼。
因此,最好在程式中添加註釋,以用自然語言解釋程式在做什麼。這些註釋稱為註釋,它們以#符號開頭
# compute the percentage of the hour that has elapsed
percentage = (minute * 100) / 60
在這種情況下,註釋出現在一行中。您也可以將註釋放在一行的末尾
percentage = (minute * 100) / 60 # percentage of an hour
從#到行尾的所有內容都會被忽略——它不會對程式產生任何影響。
註釋在記錄程式碼的非明顯特徵時最有用。可以合理地假設讀者可以弄清楚程式碼做什麼;解釋為什麼更有用。
此註釋與程式碼冗餘且無用
v = 5 # assign 5 to v
此註釋包含程式碼中沒有的有用資訊
v = 5 # velocity in meters/second.
好的變數名可以減少對註釋的需要,但過長的名稱會使複雜的表示式難以閱讀,因此存在權衡。
除錯
[edit | edit source]此時,您最有可能遇到的語法錯誤是無效的變數名,例如class以及yield,它們是關鍵字,或者 odd~job 和 US$,它們包含無效字元。
如果您在變數名中放一個空格,Python 會認為它是兩個沒有運算子的運算元
>>> bad name = 5
SyntaxError: invalid syntax
對於語法錯誤,錯誤訊息並沒有多大幫助。最常見的錯誤訊息是SyntaxError: invalid syntax以及SyntaxError: invalid token,它們都不太具有資訊量。
您最有可能遇到的執行時錯誤是“使用前定義”;也就是說,在為變數賦值之前嘗試使用它。如果拼錯了變數名,就會發生這種情況
>>> principal = 327.68
>>> interest = principle * rate
NameError: name 'principle' is not defined
變數名區分大小寫,因此LaTeX與latex.
不同
>>> 1.0 / 2.0 * pi
此時,語義錯誤最有可能的原因是運算順序。例如,要計算 1/2 π,您可能會嘗試編寫
但除法首先發生,因此您將得到 π / 2,它與 1/2 π 不一樣!Python 無法知道您想要寫什麼,因此在這種情況下您不會收到錯誤訊息;您只會得到錯誤的答案。
詞彙表- [edit | edit source]
- 值
- 資料的基本單元之一,例如數字或字串,程式對其進行操作。
- 型別int值的類別。到目前為止,我們看到的型別是整數(型別float),浮點數(型別str).
- ),和字串(型別
- 整數
- 表示整數的型別。
- 浮點數
- 表示帶小數部分的數字的型別。
- 字串
- 表示字元序列的型別。
- 變數
- 指代值的名稱。
- 語句
- 代表命令或操作的程式碼部分。到目前為止,我們看到的語句是賦值和 print 語句。
- 賦值
- 將值賦給變數的語句。
- 狀態圖
- 一組變數及其所指值的圖形表示。
- 關鍵字if, def編譯器用來解析程式的保留字;您不能使用諸如while和
- 之類的關鍵字作為變數名。
- 運算子
- 表示簡單計算的特殊符號,例如加法、乘法或字串串聯。
- 運算元
- 運算子作用的值之一。
- 向下取整除法
- 將兩個數字相除並砍掉小數部分的操作。
- 表示式
- 表示單個結果值的變數、運算子和值的組合。
- 計算
- 透過按順序執行運算來簡化表示式以生成單個值。
- 優先順序規則
- 控制包含多個運算子和運算元的表示式計算順序的規則集。
- 串聯
- 將兩個運算元首尾相連。
- 註釋
程式中的資訊,意在供其他程式設計師(或閱讀原始碼的任何人)使用,對程式執行沒有影響。
練習[edit | edit source]
練習 3[edit | edit source]
width = 17
height = 12.0
delimiter = '.'
假設我們執行以下賦值語句
width/2
width/2.0
height/3
1 + 2 * 5
delimiter * 5
對於以下每個表示式,寫出表示式的值和型別(表示式的值的型別)。
使用 Python 直譯器檢查您的答案。
練習 4[edit | edit source]
- 半徑為 的球體的體積為 4/3 π 。半徑為 5 的球體的體積是多少?提示:392.6 是錯誤的!
- 假設一本圖書的定價為 24.95 美元,但書店可以享受 40% 的折扣。第一本圖書的運費為 3 美元,每增加一本圖書運費為 75 美分。60 本圖書的批發價是多少?
- 如果我早上 6:52 離開家,以輕鬆的速度(每英里 8:15)跑 1 英里,然後以中速(每英里 7:12)跑 3 英里,最後再以輕鬆的速度跑 1 英里,我幾點回到家吃早餐?
- ↑ 在 Python 3.0 中,此除法的結果為 float。新運算子 // 執行整數除法。