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 布爾型

在Python中布爾型嚴格來說也是整數的一種,布爾型只有兩個值,TrueFalse,主要運用在邏輯運算上。

任意一個類型的對象都可以通過bool()轉換爲對應的布爾值,實際程序中可能很少會用到這個函數,但是必須要牢記不同對象對應的布爾值是什麼,規則如下:

  • 數字(int,float,complex)只要爲0,對應布爾值就是False,反之爲True
  • 空的容器對象(空的str、list、tuple、dict、set)在Python中的布爾值都是 False、非空的爲True
  • 沒有__nonzero__()方法的對象的默認值是True

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 ,分別對應與、或、非。也常用在條件判斷中,例如if a and b:…
if not b:…

注意Python中邏輯運算不會直接返回bool值(TrueFalse),實際規則如下:

邏輯表達式 返回規則
x and y 如果 bool(x) 爲 False,x and y 返回 x,否則返回 y 。
x or y 如果 bool(x) 爲 True,x and y 返回 x,否則返回 y 。
not x 如果 bool(x) 爲 False,not x 返回 True,否則返回 False 。

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章