Python 可以像一個美化的計算器一樣,進行簡單的計算。只要輸入一個表達式,Python 就會對其求值。按 Enter 後,結果立即出現。可以使用加法 (+) 和減法 (–) 運算子對數字進行加法和減法。例如:
1 + 2
## 3
1 + 3.5
## 4.5
-1 + 2.5
## 1.5
100-45
## 55
-1.1 + 5
## 3.9
若要相乘,請使用乘法 (*) 運算子:
3*2
## 6
3.5 * 1.5
## 5.25
若要進行除法,請使用除法 (/) 運算子:
3/2
## 1.5
4/2
## 2.0
正如您所看到的,當您要求 Python 執行除法運算時,它也會傳回數字的小數部分。如果您希望結果為整數形式,並刪除所有小數值,則應使用向下取整除法 (//) 運算子:
3//2
## 1
取整除法運算子將第一個數字除以第二個數字,然後將結果向下捨去到下一個最低整數。當其中一個數字為負數時,結果會變得有意思。例如:
-3//2
## -2
最終結果是比除法運算結果小的整數(-3/2 = -1.5,因此最終結果為-2)。
另一方面,如果您只需要餘數,則應使用模 (%) 運算子:
9%2
## 1
您可以使用指數 (**) 運算子計算數字的冪。下面的例子說明了這一點:
2**2
## 4
2**10
## 1024
1**10
## 1
我們也可以使用指數符號來計算小於 1 的冪。 例如,數字 \(n\) 的平方根可以表示為 \(n^{1/2}\) ,平方根可以表示為 \(n^{1/3}\) :
8**(1/3)
## 2.0
如以下範例所示,您可以使用括號將數學運算組合成更複雜的表達式。 Python 將依照標準 PEMDAS 計算順序規則(括號、指數、乘法、除法、加法和減法)計算表達式。考慮以下兩個表達式-一個不帶括號,一個有括號:
5 + 5 * 5
## 30
(5 + 5) * 5
## 50
當我們開始設計更複雜的 Python 程式時,我們會為數字分配名稱——有時是為了方便,但大多數是出於需要。這是一個簡單的例子:
# (1)
a = 3
a + 1
## 4
# (2)
a = 5
a + 1
## 6
在(1)處,我們將名稱 \(a\) 指派給數字 3。在 (2) 處,我們將 \(a\) 的值改為 5,這反映在第二個加法運算中。使用名稱 \(a\) 很方便,因為您可以簡單地更改 a 指向的數字,並且當 \(a\) 之後的任何地方引用 \(a\) 時,Python 都會使用這個新值。這種名稱稱為 標籤。您可能已經在其他地方了解到術語 “變數” 來描述相同的想法。然而,考慮到該變數也是一個數學術語(用於指稱方程式 \(x + 2 = 3\) 中的 \(x\) 之類的東西),在本書中,我僅在數學方程式和表達式的上下文中使用術語變數。
您可能已經注意到,我使用了兩種數字來演示數學運算:不含小數點的數字(您已經知道它為整數)和帶小數點的數字(程式設計師稱之為浮點數)數字。無論數字是整數、浮點小數、分數或羅馬數字,我們人類在辨識和處理數字時都沒有困難。但在我們在本書中編寫的一些程式中,只有對特定類型的數字執行任務才有意義,因此我們經常需要編寫一些程式碼來讓程式檢查我們是否需要執行任務。 Python 將整數和浮點數視為不同的型別。如果你使用函數 \(type()\),Python 會告訴你剛剛輸入的數字類型。例如:
type(3)
## <class 'int'>
type(3.5)
## <class 'float'>
type(3.0)
## <class 'float'>
在這裡,您可以看到 Python 將數字 3 分類為整數(類型「int」),但將 3.0 分類為浮點數(類型「float」)。我們都知道 3 和 3.0 在數學上是等價的,但在許多情況下,Python 會以不同的方式處理這兩個數字,因為它們是兩種不同的類型。
我們在本章中編寫的一些程式只有在輸入整數時才能正常運作。正如我們剛才看到的,Python 不會將 1.0 或 4.0 這樣的數字識別為整數,因此如果我們想接受這樣的數字作為這些程式中的有效輸入,我們必須將它們從浮點數轉換為整數。幸運的是,Python 中有一個內建函數可以做到這一點:
int(3.8)
## 3
int(3.0)
## 3
函數 \(int()\) 接受輸入浮點數,去掉小數點後面的任何內容,然後傳回結果整數。 \(float()\) 函數的工作方式與執行反向轉換類似:
float(3)
## 3.0
\(float()\) 取得輸入的整數並添加小數點以將其轉換為浮點數。
Python 也可以處理分數,但要做到這一點,我們需要使用 Python 的 fractions 模組。您可以將模組視為其他人編寫的可以在自己的程式中使用的程式。模組可以包含類別、函數,甚至標籤定義。它可以是 Python 標準函式庫的一部分,也可以從第三方位置分發。在後一種情況下,您必須先安裝該模組才能使用它。
Fractions 模組是標準函式庫的一部分,這表示它已經安裝了。它定義了一個 Fraction 類,我們將用它來將分數輸入到我們的程式中。在使用它之前,我們需要導入它,這是告訴 Python 我們想要使用該模組中的類別的一種方式。讓我們來看一個簡單的範例 - 我們將建立一個新標籤 \(f\),它引用分數 \(3/4\):
# (1)
from fractions import Fraction
# (2)
f = Fraction(3, 4)
# (3)
f
## Fraction(3, 4)
我們先從分數模組導入 Fraction 類別(1)。接下來,我們透過將分子和分母作為參數 傳遞來建立此類別的物件 (2)。當我們印出物件(3)時,Python 以 Fraction(numerator, denominator) 的形式顯示分數。
基本的數學運算,包含比較運算,都對分數有效。您也可以將分數、整數和浮點數組合在一個表達式中:
Fraction(3, 4) + 1 + 1.5
## 3.25
當表達式中有浮點數時,表達式的結果以浮點數形式傳回。另一方面,當表達式中只有分數和整數時,即使結果的分母為 1,結果也是分數。
Fraction(3, 4) + 1 + Fraction(1/4)
## Fraction(2, 1)
到目前為止我們看到的數字都是所謂的實數。 Python 也支援複數,其虛部由字母 \(j\) 或 \(J\) 標識(而不是數學符號中使用的字母 \(i\))。例如,複數 \(2 + 3i\) 在 Python 中可以寫成 \(2 + 3j\):
a = 2 + 3j
type(a)
## <class 'complex'>
正如你所看到的,當我們對複數使用 \(type()\) 函數時,Python 告訴我們這是一個複數類型的物件。您也可以使用 \(complex()\) 函數定義複數:
a = complex(2, 3)
a
## (2+3j)
這裡我們將複數的實部和虛部作為兩個參數傳遞給 \(complex()\) 函數,它傳回一個複數。您可以像實數一樣進行複數加減運算:
b = 3 + 3j
a + b
## (5+6j)
a - b
## (-1+0j)
複數的乘法和除法也類似地進行:
a * b
## (-3+15j)
a / b
## (0.8333333333333334+0.16666666666666666j)
模數 (%) 和取整除法 (//) 運算對於複數無效。可以使用複數的 real 和 imag 屬性來檢索複數的實部和虛部,如下所示:
z = 2 + 3j
z.real
## 2.0
z.imag
## 3.0
複數的共軛具有相同的實部,但虛部具有相同的大小和相反的符號。可以使用 \(conjugate()\) 方法得到:
z.conjugate()
## (2-3j)
實部和虛部都是浮點數。使用實部和虛部,您可以使用以下公式計算複數的大小,其中 \(x\) 和 \(y\) 分別是該數的實部和虛部: \(\sqrt{x^2+y^2}\) ,在 Python 中,這看起來如下所示:
(z.real ** 2 + z.imag ** 2) ** 0.5
## 3.605551275463989
尋找複數大小的更簡單方法是使用 \(abs()\) 函數。當使用實數作為參數呼叫時,\(abs()\) 函數會傳回絕對值。例如,\(abs(5)\) 和 \(abs(-5)\) 都傳回 \(5\)。但是,對於複數,它會傳回大小:
abs(z)
## 3.605551275463989
標準庫的 cmath 模組(用於複數數學的 cmath)提供了對許多其他專用函數的存取來處理複數。
當我們開始編寫程式時,透過 \(input()\) 函數來接受使用者輸入 是一個很好、很簡單的方法。這樣,我們就可以編寫程式要求使用者輸入一個數字,對該數字執行特定的操作,然後顯示操作的結果。讓我們看看它的實際效果:
# (1)
# a = input()
# 1
# (2)
在 (1) 處,我們呼叫 \(input()\) 函數,該函數等待您輸入一些內容,如 (2) 處所示,然後按 Enter 。提供的輸入儲存在 \(a\) 中:
# a
# (3)
請注意 (3) 處 \(1\) 周圍的單引號。 \(input()\) 函數以 string 形式傳回輸入。在 Python 中,字串是兩個引號之間的任意字元集。當你想要建立一個字串時,可以使用單引號或雙引號:
s1 = 'a string'
s2 = "a string"
這裡,s1 和 s2 都指同一個字串。即使字串中唯一的字元是數字,Python 也不會將該字串視為數字,除非我們去掉這些引號。因此,在我們對輸入執行任何數學運算之前,我們必須將其轉換為正確的數字類型。可以分別使用 \(int()\) 或 \(float()\) 函數將字串轉換為整數或浮點數:
a = '1'
int(a) + 1
## 2
float(a) + 1
## 2.0
這些與我們之前看到的 \(int()\) 和 \(float()\) 函數相同,但這次不是將輸入從一種數字轉換為另一種數字,而是將字串作為輸入 (‘1’) 並傳回一個數字(2 或 2.0)。但值得注意的是,\(int()\) 函數無法將包含浮點小數的字串轉換為整數。如果您採用具有浮點數的字串(例如 “2.5” 甚至 “2.0”)並將該字串輸入到 \(int()\) 函數中,您將收到一條錯誤訊息:
# int('2.0')
## Traceback (most recent call last):Working with Numbers 9 File "<pyshell#26>", line 1, in <module>int('2.0') ValueError: invalid literal for int() with base 10: '2.0'
這是一個異常的範例 - Python 告訴您由於錯誤而無法繼續執行程式的方式。在本例中,異常的類型為 ValueError。 (有關異常的快速回顧,請參閱附錄 B。)類似地,當您提供小數(例如 \(3/4\))作為輸入時,Python 無法將其轉換為等效的浮點數或整數。再次引發 ValueError 異常:
# a = float(input())
## 3/4
### Traceback (most recent call last):File "<pyshell#25>", line 1, in <module> a=float(input()) ValueError: could not convert string to float: '3/4'
您可能會發現在 try… except 區塊中執行轉換很有用,這樣您就可以處理此異常並警告使用者程式遇到了無效輸入。接下來我們將看看 try… except 區塊。
如果您不熟悉try…except,基本思想是這樣的:如果您在try… except 區塊中執行一個或多個語句,並且在執行時出現錯誤,您的程式將不會崩潰並列印回溯。相反,執行會轉移到 except 區塊,您可以在其中執行適當的操作,例如,列印有用的錯誤訊息或嘗試其他操作。
這是您在 try… except 區塊中執行上述轉換並在無效輸入時列印有用的錯誤訊息的方法:
# try:
# a = float(input('Enter a number: '))
# except ValueError:
# print('You entered an invalid number')
請注意,我們需要指定要處理的異常類型。這裡,我們要處理 ValueError 異常,所以我們將其指定為 except ValueError。現在,當您給出無效輸入(例如 \(3/4\))時,它會列印一個有用的錯誤訊息,如圖所示
# Enter a number:
## 3/4
### u You entered an invalid number
您也可以使用 input() 函數指定提示,告訴使用者需要什麼類型的輸入。例如:
# a = input('Input an integer: ')
使用者現在將看到提示輸入一個整數作為輸入的訊息:
# Input an integer: 1
在本書的許多程式中,我們會要求使用者輸入數字作為輸入,因此我們必須確保在嘗試對這些數字執行任何操作之前進行轉換。您可以將輸入和轉換合併在一語句中,如下所示:
# a = int(input())
## 1
a = 1
a + 1
## 2
如果使用者輸入一個整數,這非常有效。但正如我們之前看到的,如果輸入是浮點數(即使是相當於整數的數字,例如 1.0),也會產生錯誤:
# a = int(input())
## 1.0
### Traceback (most recent call last):File "<pyshell#42>", line 1, in <module> a=int(input()) ValueError: invalid literal for int() with base 10: '1.0'
為了避免此錯誤,我們可以設定一個 ValueError 捕獲,就像我們之前看到的分數捕獲一樣。這樣程式將捕獲浮點數,這在處理整數的程式中不起作用。然而,它也會標記像 1.0 和 2.0 這樣的數字,Python 將其視為浮點數,但它們等效於整數,並且如果將它們作為正確的 Python 類型輸入,則可以正常工作。
為了解決這一切,我們將使用 is_integer() 方法來過濾掉小數點後有效數字的任何數字。 (此方法僅針對 Python 中的浮點數類型數字定義;它不適用於已經以整數形式輸入的數字。)
下面是一個範例:
1.1.is_integer()
## False
這裡,我們呼叫 is_integer() 方法來檢查 1.1 是否是整數,結果是 False,因為 1.1 確實是浮點數。另一方面,使用數字 11 時,當使用 1.0 作為浮點數呼叫方法時,結果為 True:
1.0.is_integer()
## True
我們可以使用 is_integer() 過濾掉非整數輸入,同時保留像 1.0 這樣的輸入,它表示為浮點數,但相當於整數。稍後我們將看到該方法如何適合於更多的程式。
我們之前了解的 Fraction 類別也能夠將“3/4”等字串轉換為 Fraction 物件。事實上,這就是我們接受分數作為輸入的方式:
# a = Fraction(input('Enter a fraction: '))
## Enter a fraction: 3/4
### a
#### Fraction(3, 4)
試著輸入一個分數(例如 3/0)作為輸入:
# a = Fraction(input('Enter a fraction: '))
## Enter a fraction: 3/0
### Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> a = Fraction(input('Enter a fraction: ')) File "/usr/lib64/python3.3/fractions.py", line 167, in __new__raise ZeroDivisionError('Fraction(%s, 0)' % numerator) ZeroDivisionError: Fraction(3, 0)
ZeroDivisionError 異常訊息告訴您(如您已經知道的)分母為 0 的分數是無效的。如果您打算讓使用者在您的程式之一中輸入分數作為輸入,那麼始終掌握此類異常是一個好主意。這是你可以做類似事情的方法:
# try:
## a = Fraction(input('Enter a fraction: '))
### except ZeroDivisionError:
#### print('Invalid fraction')
##### Enter a fraction: 3/0
### Invalid fraction
現在,每當程式的使用者輸入分母為 0 的分數時,它都會列印訊息無效分數 (Invalid fraction)。
類似地,complex() 函數可以將「\(2+3j\)」等字串轉換為複數:
# z = complex(input('Enter a complex number: '))
## Enter a complex number: 2+3j
### z
#### (2+3j)
如果輸入字串為 ‘\(2 \ + \ 3j\)’ (有空格),則會導致 ValueError 錯誤訊息:
# z = complex(input('Enter a complex number: '))
## Enter a complex number: 2 + 3j
### Traceback (most recent call last): File "<pyshell#43>", line 1, in <module> z = complex(input('Enter a complex number: ')) ValueError: complex() arg is a malformed string
將字串轉換為複數時最好捕獲 ValueError 異常,就像我們對其他數字類型所做的那樣。
現在我們已經學習了一些基本概念,我們可以將它們與Python的條件和循環語句結合起來,製作一些更高級和有用的程式。
當一個非零整數 \(a\) 除另一個整數 \(b\) 時,餘數為 \(0\),則稱 \(a\) 為 \(b\) 的因數。例如,\(2\) 是所有偶數的因數。我們可以寫一個如下所示的函數來找出非零整數 \(a\) 是否是另一個整數 \(b\) 的因數:
def is_factor(a, b):
if b % a == 0:
return True
else:
return False
我們使用本章前面介紹的 % 運算子來計算餘數。如果您發現自己問過類似「\(4\) 是 \(1024\) 的因數嗎?」之類的問題,您可以使用 is_factor() 函數:
is_factor(4, 1024)
## True
對於任何正整數 \(n\),我們如何找到它的所有正因數?對於 \(1\) 到 \(n\) 之間的每個整數,我們檢查 \(n\) 除以該整數後的餘數。如果餘數為 \(0\),則它是一個因數。我們將使用使用數字 range() 函數來編寫一個程式,該程式將遍歷 \(1\) 到 \(n\) 之間的每個數字。
在寫完整的程式之前,我們先來看看 range() 是如何運作的。 range() 函數的典型用法如下所示:
for i in range(1, 4):
print(i)
## 1
## 2
## 3
在這裡,我們設定了一個 for 循環,並為 range 函數提供了兩個參數。 range() 函數從第一個參數(起始值)指定的整數開始,一直到第二個參數指定的整數(停止值)之前的整數。在本例中,我們告訴 Python 列印該範圍內的數字,從 \(1\) 開始到 \(4\) 停止。 。
同樣重要的是要注意 range() 函數只接受整數作為其參數。您也可以使用 range() 函數而不指定起始值,在這種情況下假定起始值為 \(0\)。
for i in range(5):
print(i)
## 0
## 1
## 2
## 3
## 4
range() 函數產生的兩個連續整數之間的差稱為 step value。預設情況下,step value 為 \(1\)。例如,以下程式列印 \(10\) 以下的奇數:
for i in range(1,10,2):
print(i)
## 1
## 3
## 5
## 7
## 9
好的,現在我們已經了解了 range() 函數的工作原理,我們準備好看看因子計算程式了。因為我正在編寫一個相當長的程序,所以我沒有在互動式 IDLE 提示字元中編寫該程序,而是在 IDLE 編輯器中編寫它。您可以透過在 IDLE 中選擇 File \(\triangleright\) New Window 來啟動編輯器。請注意,我們首先用三個單引號 (’) 註解我們的程式碼。這些引號之間的文字不會作為程式的一部分由 Python 執行;這只是對我們人類的註解。
'''
Find the factors of an integer
def factors(b):
for i in range(1, b+1):
if b % i == 0:
print(i)
if __name__ == '__main__':
b = input('Your Number Please: ')
b = float(b)
if b > 0 and b.is_integer():
factors(int(b))
else:
print('Please enter a positive integer')
'''
## "\nFind the factors of an integer\n \n\ndef factors(b):\n \n for i in range(1, b+1):\n if b % i == 0:\n print(i)\n \nif __name__ == '__main__':\n \n b = input('Your Number Please: ')\n b = float(b)\n \n if b > 0 and b.is_integer():\n factors(int(b))\n else:\n print('Please enter a positive integer')\n"
Factors() 函數定義了一個 for 循環,使用 range() 函數對 \(1\) 和 \(b+1\) 處的輸入整數之間的每個整數迭代一次。在這裡,我們要迭代到使用者輸入的整數 \(b\),因此停止值表示為 \(b+1\)。對於每個整數 \(i\),程式都會檢查輸入數字是否沒有餘數,如果是,則列印它。當您執行程式(透過選擇 Run \(\triangleright\) Run Module)時,它會要求您輸入一個數字。如果您的數字是正整數,則會列印其因子。例如:
'''
Your Number Please: 25
1
5
25
'''
## '\nYour Number Please: 25\n1\n5\n25\n'
如果您輸入非整數或負整數作為輸入,程式會列印錯誤訊息,要求您輸入正整數:
'''
Your Number Please: 15.5
Please enter a positive integer
'''
## '\nYour Number Please: 15.5\nPlease enter a positive integer\n'
這是一個範例,說明我們如何透過始終檢查程式本身中的無效輸入來使程式更加用戶友好。因為我們的程式只用來找出正整數的因子,所以我們使用 is_integer() 方法檢查輸入數字是否大於 \(0\) 並且是整數,以確保輸入有效。如果輸入不是正整數,程式會列印一條方便使用的指令,而不僅僅是一個大的錯誤訊息。