1. 程式人生 > >Python自學指南---基礎篇(五)資料型別-Number

Python自學指南---基礎篇(五)資料型別-Number

前一節中,我們對Python中的物件有了一個基本的瞭解。從本節開始,我們將分別瞭解不同型別的物件,並且對不同物件的特點,特別是物件有關的函式進行介紹。

本節將會介紹數字型別,也就是Number型別,在Python中是一種不可變型別

5.1 整數

Python能夠處理任意大小的整數,例如0,-1,9989080等等 除了用一般的十進位制表示,也可以用二進位制(0x)、八進位制(0b)、十六進位制表示(0o)。並且不同進位制的轉換有相應的內建函式:

print("十進位制數為:", 5)
print("轉換為二進位制為:", bin(5))
print("轉換為八進位制為:", oct(5))
print(
"轉換為十六進位制為:", hex(5))

執行結果為:

十進位制數為:5
轉換為二進位制為: 0b101     
轉換為八進位制為: 0o5      
轉換為十六進位制為: 0x5

5.2 浮點數

浮點數也就是小數,例如3.14,5.34,-0.3等等,也可以用科學計數法表示,用e來代替10,例如3.14x109 就要用3.14e9來表示。

5.3 複數

Python中複數的表示與我們在課本中學到的一致,分為實部和虛部,虛部末尾需要加j或J,例如4.2+5j43-0.9J。需要注意的是,Python中複數的實部和虛部都是浮點數

複數物件主要的兩個屬性就是real、imag,分別返回實部和虛部,還有一個conjugate方法,返回共軛複數

>>> num = 4.2+5j
>>> 
>>> num.real
4.2
>>> num.imag
5.0
>>> num.conjugate()
(4.2-5j)

5.4 布林型

布林型只有兩個值,TrueFalse,主要運用在邏輯運算上。

5.5 運算子與重要的內建函式

瞭解了各種數字型別之後,接下來就是學習在程式中如何使用它們,這就涉及到各種不同的運算子以及內建函式。

5.5.1 算數運算子

算數運算子包括加減乘除(+,-,*,/,//),取餘(%),冪運算(**)。算數運算子的使用有以下幾個需要注意的要點

  1. 運算元型別不一

舉個例子,在使用加法的時候,用一個整數加小數是很常見的,譬如9.8+1但理論上,Python中使用+時,左右兩個運算元應當是相同型別。之所以9.8+1這個表示式依然可以正確地執行,是因為Python使用了隱式的數字型別強制轉換機制來保證運算元型別一致。

強制轉換的機制可以參考《Python核心程式設計》中的描述:

如果有一個運算元是複數, 另一個運算元被轉換為複數。 否則,如果有一個運算元是浮點數, 另一個運算元被轉換為浮點數。 否則, 如果有一個運算元是長整數,則另一個運算元被轉換為長整數; 否則,兩者必然都是普通整數,無須型別轉換。

強制轉換的規則很好理解,只要記住**精度低的運算元向精度較高的運算元看齊(有時會把精度更高稱作“更寬的型別”)**就可以了。例如9.8+1,Python會把1隱式地轉換為浮點數。

強制轉換是一種隱式轉換,不需要程式設計師的參與,當然Python也提供了一些顯式的型別轉換函式,分別為int(),float(),complex()

  1. true除法和floor除法

在Python2.2之前的版本中,表示除法的運算子只有/這一個,它可以進行兩種型別的除法:

  • floor除法:即“地板除”,兩個運算元都是整數,返回的是不大於正確結果的最大整數。有一些教程中會說截取了結果的小數部分,這種說法是恰當的,因為結果為負數的時候不符合這個規則:
#Python 2.7.13
>>> 1 / 2
0
>>> -1 / 2
-1         #結果是-1而不是0
  • true除法:只要有一個運算元是浮點數,結果返回的就是浮點數:
#Python 2.7.13
>>> 1.0 / 2
0.5
>>> 1 / 2.0
0.5
>>> 1 / float(2)
0.5

在Python2.2之後,設計者們為了使語言更加簡潔明瞭,就將floor除法的功能剝離出來,用//來表示。這樣,無論運算元是整數還是浮點數,//都將執行floor除法:

>>> 1 // 2
0
>>> 1.0 // 2
0
>>> 1 // 2.0
0

不過,只要你使用的是Python2.x,你就會發現/仍然可以表示true除法和floor除法。在Python3.x中,/才變成了僅代表true除法

#Python 3.x
>>> 1 / 2
0.5
>>> 1.0 / 2
0.5
>>> 1 / 2.0
0.5

如果你希望在Python2.x中讓/只表示true除法,可以在程式中加入這樣一條語句from __future__ import division

  1. 取餘運算

取餘隻需要記住一個要點:取餘過程中的一定是整數,並且是通過floor除法得到的整數。

  1. 冪運算

冪運算**需要注意優先順序問題。

首先,一元操作符(+,-代表取正,取負)的優先順序大於加減乘除和取餘(+,-,*,/,//,%)運算,可以用一個例子來理解:

>>> -1 // 2
-1
>>> -(1 // 2)
0

這裡的-表示取負數,優先順序一定大於//,編寫程式的時候保險起見也可以加上括號,-1 // 2其實也就等價於(-1) // 2

冪運算**比較特殊,它會比左側運算元的一元運算子優先順序高,這也就是說-1 ** 2(-1) ** 2不等價:

>>> -1 ** 2   #冪運算先計算
-1
>>> (-1) ** 2     
1

另外,除了運算子**,Python還提供了內建函式pow()用於乘方運算。

傳入兩個引數時,pow(x, y)等價於x**y

傳入三個引數時,且x,y,z都為整數時,pow(x, y, z)x ** y % z等價,而當x,y,z有一個不是整數時,pow(x, y, z)會報錯:

>>> pow(3, 6, 6.0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: pow() 3rd argument not allowed unless all arguments are integers

此外,math模組中還提供了sqrt()函式,用於開平方,不過完全可以用pow()來代替:

from math import *   #為了使用sqrt()必須匯入math模組,pow則不用
>>> sqrt(8)
2.8284271247461903
>>> pow(8,0.5)   #開平方
2.8284271247461903
>>> pow(8,1/3)   #開三次方
2.0

5.5.2 比較運算子

比較運算子包括==,!=,>,<,>=,<= ,運算返回的結果是bool值(TrueFalse),常用在條件判斷中,例如if a != b:…

5.5.3 邏輯運算子

邏輯運算子包括and,or,not ,分別對應與、或、非。運算返回的結果是bool值(TrueFalse),也常用在條件判斷中,例如if a and b:… if not b:…

5.5.4 成員運算子

成員運算子包括in,not in ,可以用於判斷特定的物件是否存在於序列中中,運算返回的結果是bool值(TrueFalse

>>> 1 in [1, 2, 3]
True
>>> 'd' in "abc"
False

in一般會與for連用,用於遍歷序列,例如下面這個例子:

#判斷list_1的哪些字元存在於list_2中
list_1 = ['A','B','C','D']
list_2 = ['A','B']

for letter in list_1:
    if letter in list_2:
        print(letter+' is exists in list_2')
    else:
        print(letter+' is not exists in list_2')

執行結果:

A is exists in list_2
B is exists in list_2
C is not exists in list_2
D is not exists in list_2

5.5.5 身份運算子

身份運算子包括is,is not,用於判斷兩個變數是否引用自同一個物件,因此,a is b 也就等價於 id(a) == id(b)

5.5.6 賦值運算子

賦值運算在第二章中已經作為基本語法介紹過,主要包括的就是普通的賦值運算=,以及結合算術運算子的增量運算+=,-=,*=,/=,//=,%=,**=

5.5.7 位運算子

還有一個初學時不常用,但實際上非常實用的運算子,就是位運算子。位運算中包含運算子&,|,^,~,<<,>>

首先要記住的是,位運算的運算元都是整數,並且運算針對的是整數的二進位制形式

先介紹&,|,^ 這三個運算子,它們分別被稱為“按位與”、“按位或”、“按位異或”。先說&,實際上就是把左右兩個運算元的二進位制形式逐位進行與運算,得到一個新的二進位制數,用一個例子來理解:

>>> a = 60      # 60 = 0011 1100 
>>> b = 13      # 13 = 0000 1101 
>>> a & b
12              # 12 = 0000 1100

以此類推,|、^就是將每一位上的與運算改為或運算和異或運算即可。

運算子的作用是“按位取反”,顧名思義,就是將二進位制的每一位1變為0,0變為1。

<<,>>是左移運算子和右移運算子,用於將運算數的各二進位全部左移或右移若干位

>>> a = 13     # 13 = 0000 1101 
>>> a << 1     
26             # 26 = 0001 1010 
>>> a << 2
52             # 52 = 0011 0100 
>>> a >> 1
6              # 6 = 0000 0110 

除了各類運算子之外,還有一些針對數字型別物件的內建函式需要了解

5.5.8 舍入函式

  1. floor(x) floor代表地板,那麼顧名思義,就是在傳入引數的“下面”,即取不大於傳入引數的最大整數:
>>> floor(1.3)
1
>>> floor(-1.3)
-2
  1. ceil(x) ceil代表房頂,就是在傳入引數的“上面”,即取不小於傳入引數的最小整數:
>>> ceil(1.3)
2
>>> ceil(-1.3)
-1
  1. round(x, [, n] ) (這裡x不能預設,代表目標運算元,而n是可以預設的,代表保留幾位小數,預設為0)

人們有時候會說round()的作用是四捨五入:

>>> round(8.2)
8
>>> round(-9.6)
-10

round()也可以指定保留幾位小數:

>>> round(8.5)
8
>>> round(56.659, 1)
56.7

不過在使用的時候,可能會發現一些問題:

在python2.x中執行:

>>> round(2.5)
3.0
>>> round(-2.5)
-3.0

在python3.x中執行:

>>> round(2.5)
2
>>> round(-2.5)
-2
>>> round(3.5)
4
>>> round(-3.5)
-4

因此準確來說,round()一方面可以完成的是四捨六入的功能;另一方面,當傳入的數字與兩側整數距離相同的時候,python2.x的做法是:保留到離0較遠的一側,而python3.x的做法是:保留到偶數的一側

需要注意的是,上述規則適用於傳入的數字與兩側整數距離相同的時候,那麼按理來說,無論python2.x還是python3.x,round(2.675, 2)的結果都應該是2.68,但是實際上結果卻是2.67!這主要是因為2.675轉換為二進位制之後,小數點後面的位數太多了(大約是10.10101100110011001100110011001100110011001100……),超出了計算機能夠表示的精度,因此小數點後面的一串二進位制數已經被截斷了一部分,因此2.675在計算機中並不能精確表示,而是離2.67更近一些,使用round()時直接舍到2.67即可。

可見,round()結果會受到計算機本身表示精度的影響,因此可能會帶來一些意想不到的結果,如果對精度要求高的計算,儘量避免使用round() ,一些替代的方案可以參考這篇blog: http://www.runoob.com/w3cnote/python-round-func-note.html

5.5.9 random模組

random模組中包含了多個生成隨機數物件的函式,是Python中的一個非常常用的模組。

在使用random模組前需要匯入:

import random

這裡提一個程式碼風格上的問題。我們在之前匯入math模組的時候使用的是from math import * 同樣我們可以使用import math,區別在於前者我們可以直接呼叫模組的內建函式,例如sqrt();而後者這樣匯入,我們必須採用模組.函式的格式呼叫內建函式:math.sqrt()。Python的技術規格中更建議使用後者,這是因為不同模組中可能有同名的函式,為了避免混淆,在呼叫模組內建函式的時候,最好還是在函式名前面加上模組名。

回到random模組,主要的幾個函式如下:

  1. random.random()

生成一個0到1之間的隨機浮點數,包括0但不包括1,也就是[0.0, 1.0)

>>> random.random()
0.02025527401777727
  1. random.randint(x, y)

隨機生成[x,y](包括x, y)區間內的整數,需要注意x,y都必須是整數,且x<=y

>>> random.randint(1,9)
4
  1. random.uniform(x, y)

隨機生成 [x, y) 或[y,x)區間內的浮點數,注意x,y可以不是整數,並且不用考慮大小

>>> random.uniform(10.6,1.5)
9.664643121543374
  1. random.randrange ([start,] stop [,step]) 該方法返回[start, stop),並且遞增基數為step的集合內的一個隨機整數。start預設值為0,step預設值為1。注意start, stop, step都必須為整數。
>>> random.randrange(1, 100, 2)   #從1-99中選一個奇數
93
>>> random.randrange(100)   #從0-99中選一個隨機整數
2
>>> random.randrange(0, 100, 5)   #以5為遞增基數,從0-99中選一個隨機數
45

以上四個函式用於生成隨機數,下面看一個能夠控制隨機數生成的函式

  1. random.seed([x]) 傳入該函式一個固定的seed值,就能夠讓隨機數固定:
>>> random.seed( 10 )
>>> random.random()
0.5714025946899135
>>> random.seed( 10 )
>>> random.random()
0.5714025946899135
>>> random.seed( 10 )
>>> random.random()
0.5714025946899135

這其實也說明了random模組中的函式生成的是偽隨機數,即生成隨機數的演算法是固定的改變的只是演算法的引數seed值,如果不手動設定seed值,Python就會根據系統時間自行設定seed值。

接下來再看幾個與序列有關的函式,序列將會在之後的章節中詳細介紹,這裡提前接觸一下。Python中序列也就是三種:list(列表)、tuple(元組)、string(字串)。

  1. random.choice(seq)

從序列中隨機選取一個元素,並返回這個元素,seq應當是一個序列,

>>> random.choice([1, 3, 4, 6, 9])  #list(列表)
1
>>> random.choice('a string')   #string(字串)
't'
>>> random.choice((1, 4, 5, 8))  #tuple(元組)
8
  1. random.sample(seq, n)

從序列中隨機選取n個元素形成一個新的list,並返回這個list,注意n不能大於原序列seq的長度。

>>> random.sample([1, 3, 4, 6, 9], 3)
[1, 9, 6]
>>> random.sample('a string', 3)
['g', 'i', 'a']
>>> random.sample((1, 4, 5, 8), 3)
[8, 1, 4]

需要注意,無論是random.choice()還是random.sample(),都不會改變傳入的原序列,而以下這個函式則不同。

  1. random.shuffle(seq)

該函式可以將序列seq中的元素打亂,random.shuffle()沒有返回值,它是直接改變原序列seq。

>>> list_1 = [1, 3, 4, 6, 9]
>>> random.shuffle(list_1)     ##本身沒有返回值
>>> list_1
[9, 1, 4, 6, 3]
>>> print(random.shuffle(list_1)) ##再次證明本身沒有返回值
None

本章的內容較多,梳理一下結構: 在這裡插入圖片描述