Learning Python Part I之數字類型(Numeric Types)

在Python中,數據都採用對象的形式–包括Python內置的對象和我們通過Python工具或其他語言例如C等創造的對象,對象是Python中最基本的概念。

數字類型基礎

在Python中,數字並不是單一的對象類型,而是包含一類相似的類型,Python支持通常的數字類型如整數和浮點型,而且支持更高級的數字類型和對象,Python中的數字工具包括:

  1. 整型和浮點型對象(integer and float-point objects)
  2. 複數對象(Complex number objects)
  3. 十進制運算(Decimal)
  4. 分數(Fraction)
  5. 集合(Sets)
  6. 布爾型(Booleans)
  7. 內置函數和模塊(Build-in function and modules)
  8. 表達式,無限制的整數精度,位操作,十六進制,十進制和二進制的格式化
  9. 第三方擴展(Third-party extensions)

數字表達形式:

在Python中數字不需要提前聲明,但在使用前必須提前賦值,否則會報錯(或者說必須有初始值),並且在Python2.x中,整數包含兩種類型:短型(normal)和長型(long),當數字過大時Python會在內部自動將數字轉爲長型,以L結尾標註;但在Python3.x中,整數只是一種單一的類型,不在區分,方便的同時當數字逐漸增大後運行也會相應變慢。

這裏寫圖片描述

表達式運算符

表達式是最基本的處理數字的工具,下表列出了Python中可用的算符:

這裏寫圖片描述

值得注意的是 ( A < B < C ) 和 ( A < B and B < C ) 等價的;還有數字比較符是基於大小的,當遇到浮點型的時候可能並不會像想象的那樣工作

>>> 1.1 + 2.2 == 3.3
False
>>> 1.1 + 2.2 
3.3000000000000003
>>> int(1.1 + 2.2) == int(3.3)
True

除法:

在Python中除法,並且在2.x 和 3.x中有些區別:

X / Y :

真除;在Python2.x中會將小數部分捨去只有當除數和被除數中有小數時結果保留小數部分;在Python3.x中,無論除數和被除數類型,始終保留小數部分。

X // Y :

整除;從Python2.2之後加入的除法符號,這種除法會一直捨去小數部分,結果的類型取決於除數和被除數的類型
C:\code> C:\Python33\python
>>> 10 / 4 # Differs in 3.X: keeps remainder
2.5
>>> 10 / 4.0 # Same in 3.X: keeps remainder
2.5
>>> 10 // 4 # Same in 3.X: truncates remainder
2
>>> 10 // 4.0 # Same in 3.X: truncates to floor
2.0
C:\code> C:\Python27\python
>>> 10 / 4  # This might break on porting to 3.X!
2
>>> 10 / 4.0
2.5
>>> 10 // 4  # Use this in 2.X if truncation needed
2
>>> 10 // 4.0
2.0

如何兼容兩個版本

爲了解決 ” / ” 在不同的版本中不同的問題,可以有兩種方法使其兼容不同版本。

X = Y / Z #只是用整除,在2.x或3.x中都返回相同結果
X = Y / float(Z) #使用float()保證結果是小數

或者也可以通過import語句在2.x中打開3.x的 ” / ” 功能

>>> 10 / 4
2
>>> from __future__ import division
>>> 10 / 4
2.5
>>> 10 // 4
2

兩種舍位取整的區別(Floor versus truncation)

floor division 取的是比其小的最大整數,而truncating division 是直接捨去小數位,在運算整數時兩種沒有區別,但在運算負數時結果會不相同:

>>> import math
>>> math.floor(2.5)
2
>>> math.floor(-2.5)
-3
>>> math.trunc(2.5)
2
>>> math.trunc(-2.5)
-2

當運行除法運算符時,運行的是floor除法:
在3.x中

>>> 5 / 2, 5 / -2
(2.5, -2.5)
>>> 5 // 2, 5 // -2
(2, -3)
>>> 5 / 2.0,5 / -2.0
(2.5, -2.5)
>>> 5 // 2.0, 5 // -2.0
(2.0, -3.0)

在2.x中

>>> 5 / 2, 5 / -2
(2, -3)
>>> 5 // 2, 5 // -2
(2, -3)
>>> 5 / 2.0, 5 / -2.0
(2.5, -2.5)
>>> 5 // 2.0, 5 // -2.0
(2.0, -3.0)

複數

複數類型並不常見,他們在工程和科學計算中用的比較多。
複數可以用標準庫cmath(math模塊中的複數部分),因爲並不常見,所以不在這裏詳細介紹,用到的時候可以去查看python在線手冊

十六進制、八進制和二進制

>>> oct(64),hex(64),bin(64)
('0o100', '0x40', '0b1000000')
>>> int('64'),int('100',8),int('40', 16), int('100000', 2)
(64, 64, 64, 32)
>>> int('0x40',16),int('0b1000000',2)
(64, 64)

位操作

除了一些常用的加減操作之外,Python支持大部分C語言中的操作,這也包括處理二進制位,這些操作在Python處理例如網絡數據包、串口或者C語言產生的二進制數據包時很有用。

>>> x = 1
>>> x << 2 #將x左移兩位
4
>>> x | 2 #x 與 2  相或
3
>>> x & 1 #x 與 1 相與
>>> 1

bit_length():

這個方法可以查詢用二進制表示一個值需要多少位,不過用len()也能實現同樣的效果。

>>> x = 99
>>> bin(x) , x.bit_length(), len(bin(x)) - 2
('0b1100011', 7, 7)
>>> bin(256),(256).bit_length(), len(bin(256)) - 2
('0b100000000', 9, 9)

其他內置工具:

math模塊:

以下舉例一部分,具體的可查看python在線手冊

>>> import math
>>> math.pi, math.e
(3.141592653589793, 2.718281828459045)
>>> math.sin(2 * math.pi / 180)
0.03489949670250097 
>>> math.sqrt(144), math.sqrt(2)
(12.0, 1.4142135623730951) 
>>> pow(2, 4), 2 ** 4, 2.0 ** 4.0
(16, 16, 16.0) 
>>> abs(-42.0), sum((1, 2, 3, 4))
(42.0, 10) 
>>> min(3, 1, 2, 4), max(3, 1, 2, 4)
(1, 4)
>>> math.floor(2.567), math.floor(-2.567)
(2, −3)
>>> math.trunc(2.567), math.trunc(−2.567)
(2, −2)
>>> int(2.567), int(−2.567)
(2, −2)
>>> round(2.567), round(2.467), round(2.567, 2) # Round (Python 3.X version)
>>> '%.1f' % 2.567, '{0:.2f}'.format(2.567)
('2.6', '2.57')
>>> (1 / 3.0), round(1 / 3.0, 2), ('%.2f' % (1 / 3.0))
(0.3333333333333333, 0.33, '0.33')

三種實現求平方根的方法:

>>> import math
>>> math.sqrt(144)
12.0
>>> 144 ** .5
12.0
>>> pow(144, .5)
12.0
>>> math.sqrt(1234567890)
35136.41828644462
>>> 1234567890 ** .5
35136.41828644462
>>> pow(1234567890, .5)
35136.41828644462

random模塊:

這個模塊提供了像求隨機值,隨機挑選數字這一類的工具

>>> import random
>>> random.random()
0.25880066905091026
>>> random.random()
0.986742321398632
>>> random.randint(1,10)
10
>>> random.randint(1,10)
7
>>> import random
>>> suits = ['hearts', 'clubs', 'diamonds', 'spades']        
>>> random.shuffle(suits)
>>> suits
['hearts', 'diamonds', 'clubs', 'spades']
>>> random.shuffle(suits)
>>> suits
['diamonds', 'hearts', 'spades', 'clubs']

其他數字類型

Decimal類型

因爲存儲數值的空間有限,所以浮點型運算有時候很不精確,例如:

>>> print(0.1 + 0.1 + 0.1 - 0.3)
5.551115123125783e-17
>>> 0.1 + 0.1 + 0.1 - 0.3                                       
5.551115123125783e-17 #這個值很小,以至於與0特別接近

通過decimal,我們可以更精確的運算

>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')

設置精準度:

Decimal模塊中的其他工具可以做很多事情,例如設置精準度等。

>>> import decimal
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1428571428571428571428571429')
# Default: 28 digits
>>> decimal.getcontext().prec = 4
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1429') # Fixed precision
>>> Decimal(0.1) + Decimal(0.1) + Decimal(0.1) - Decimal(0.3)
Decimal('1.110E-17')

分數類型(Fraction)

Fraction函數實現一個有理數對象,同時保存分子和分母,如此避免浮點型運算的不精準和限制。儘管它不會像浮點型運算一樣在有限的硬件環境下取一個最接近的值,但是當以後用到時,它會提供更真實的數據。

>>> from fractions import Fraction #和random類似,需要引入模塊
>>> x = Fraction(1, 3)
>>> y = Fraction(4, 6)
>>> x , y
(Fraction(1, 3), Fraction(2, 3))
>>> print(x)
1/3

Fraction也可以進行算術運算:

>>> x + y
Fraction(1, 1)
>>> x - y
Fraction(-1, 3)
>>> x * y
Fraction(2, 9)

也可以從浮點型數據建立分數對象:

>>> Fraction('.25')
Fraction(1, 4)
>>> Fraction('1.25')
Fraction(5, 4)
>>> Fraction('.25') + Fraction('1.25')
Fraction(3, 2)

Fraction和Decimal的區別

兩種都是浮點類型運算的不同形式,浮點型運算被浮點運算硬件所限制。這種限制在所需要表示的數需要的二進制位超出了存儲空間的大小的時候更加明顯。Fraction和Decimal都是提供了一種方法獲得精確的結果,儘管以冗長的代碼和緩慢的速度(相對而言)爲代價。例如在計算0.1 + 0.1 + 0.1 - 0.3的運算中,浮點運算只會取一個無限接近與零的值,而Fraction和Decimal可以得到結果0

>>> 0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17
# This should be zero (close, but not exact)
>>> from fractions import Fraction
>>> Fraction(1, 10) + Fraction(1, 10) + Fraction(1, 10) - Fraction(3, 10)
Fraction(0, 1)
>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')

Fraction 的類型轉化和混合運算

浮點型轉化爲分數:

>>> (2.5).as_integer_ratio() #float對象的方法,生成相應的分子和分母
(5, 2)
>>> f = 2.5
>>> z = Fraction(*f.as_integer_ratio())
>>> z
Fraction(5, 2)

分數轉換爲浮點數:

>>> float(x)
0.3333333333333333
>>> float(z)
2.5
>>> float(x + z)
2.8333333333333335
>>> 17 / 6
2.8333333333333335
>>> Fraction.from_float(1.75)
Fraction(7, 4)
>>> Fraction(*(1.75).as_integer_ratio())
Fraction(7, 4)
>>> Fraction('1.75')
Fraction(7, 4)

混合運算:

>>> x
Fraction(1, 3)
>>> x + 2
Fraction(7, 3)
>>> x + 2.0
2.3333333333333335
>>> x + (1./3)
0.6666666666666666
>>> x + (4./3)
1.6666666666666665
>>> x + Fraction(4, 3)
Fraction(5, 3)

值得注意的是當把浮點型數轉換爲分數時,一些情況下會產生不可避免的精準度缺失應爲原始數據——浮點型 本身就是不精確的,必要的時候我們可以通過設置分母最大值的方法簡化結果:

>>> from fractions import Fraction
>>> 4.0 /3
1.3333333333333333
>>> 4.0 / 3
1.3333333333333333
>>> (4.0 / 3).as_integer_ratio()
(6004799503160661, 4503599627370496)
>>> x = Fraction(1, 3)
>>> a = x  + Fraction(*(4.0 / 3).as_integer_ratio())
>>> a
Fraction(22517998136852479, 13510798882111488)
>>> a.limit_denominator(10) #設置分母最大值爲10
Fraction(5, 3)

集合(sets):

集合是指一組無序的、不可變的、不重複的數據的集合,支持相應的數學集合運算理論。集合支持一些其他對象的方法,例如列表、字典等,並且集合是可迭代的,並且元素可增可減,可以包含多樣的對象類型,集合看起來和字典的鍵很相似不過支持更多的操作。
不過因爲集合是無序的而且不支持鍵值索引,所以它既不是序列也不是映射類型,而是自成一類,是一種獨特的類型。

>>> set([1, 2, 3, 4])
{1, 2, 3, 4}
>>> set('spam')
{'s', 'a', 'p', 'm'}
# Built-in: same as in 2.6
# Add all items in an iterable
>>> {1, 2, 3, 4}
{1, 2, 3, 4}
>>> S = {'s', 'p', 'a', 'm'}
>>> S
{'s', 'a', 'p', 'm'} # Set literals: new in 3.X (and 2.7)
>>> S.add('alot')
>>> S
{'s', 'a', 'p', 'alot', 'm'}
>>> S1 = {1, 2, 3, 4}
>>> S1 & {1, 3}     # Intersection
{1, 3}
>>> {1, 5, 3, 6} | S1   # Union
{1, 2, 3, 4, 5, 6}
>>> S1 - {1, 3, 4}    # Difference 
{2}
>>> S1 > {1, 3}   # Superset
True
>>> {1, 2, 3} | {3, 4}
{1, 2, 3, 4}
>>> {1, 2, 3} | [3, 4]
TypeError: unsupported operand type(s) for |: 'set' and 'list'
>>>
{1,
>>>
{1,
>>>
{1,
{1, 2, 3}.union([3, 4])
2, 3, 4}
{1, 2, 3}.union({3, 4})
2, 3, 4}
{1, 2, 3}.union(set([3, 4]))
2, 3, 4}
>>> {1, 2, 3}.intersection((1, 3, 5))
{1, 3}
>>> {1, 2, 3}.issubset(range(-5, 5))
True

不可變性

集合是一個強大而又靈活的對象,但它也有一個限制,必須銘記在心——它的元素只能是不可變對象,因此列表和字典不能夠包含在集合中,但是元組(tuples)可以。

>>> S
{1.23}
>>> S.add([1, 2, 3])
TypeError: unhashable type: 'list'  # Only immutable objects work in a set
Other Numeric Types | 167>>> S.add({'a':1})
TypeError: unhashable type: 'dict'
>>> S.add((1, 2, 3))
>>> S
{1.23, (1, 2, 3)}
>>> S | {(4, 5, 6), (1, 2, 3)}
{1.23, (4, 5, 6), (1, 2, 3)}
>>> (1, 2, 3) in S
True
>>> (1, 4, 3) in S
False

元組包含在集合中,例如可以用來代表數據、記錄、IP地址等,集合也可以包含模塊、類型對象等。集合本身也是可變的,所以不能內嵌到集合中。但frozenset內置函數工作模式和集合一樣,但建立的是不可變對象,無法更改。
當然,集合也支持列表推導式:

>>> {x for x in 'spam'}
{'m', 's', 'p', 'a'} # Same as: set('spam')
>>> {c *
{'pppp',
>>> {c *
{'pppp', # Set of collected expression results
4 for c
'aaaa',
4 for c
'aaaa',
in 'spam'}
'ssss', 'mmmm'}
in 'spamham'}
'hhhh', 'ssss', 'mmmm'}
>>> S = {c * 4 for c in 'spam'}
168 | Chapter 5: Numeric Types>>> S | {'mmmm', 'xxxx'}
{'pppp', 'xxxx', 'mmmm', 'aaaa', 'ssss'}
>>> S & {'mmmm', 'xxxx'}
{'mmmm'}

布爾型

>>> type(True)
<class 'bool'>
>>> isinstance(True, int)
True
>>> True == 1
True
>>> True is 1
False
>>> True or False
True
>>> True + 4
5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章