跳轉到內容

Python 程式設計/資料型別

來自華夏公益教科書,開放的書籍,開放的世界


資料型別決定了一個物件是否可以執行某些操作,或者它是否沒有意義。其他程式語言通常透過確保物件永遠不會儲存在將對該物件執行操作的地方來確定操作對該物件是否有意義(這種型別系統稱為靜態型別)。Python 不會這樣做。相反,它將物件的型別與物件一起儲存,並在執行操作時檢查該操作對該物件是否有意義(這稱為動態型別)。

內建資料型別

[編輯 | 編輯原始碼]

Python 的內建(或標準)資料型別可以分為幾個類別。按照官方 Python 文件中使用的層次結構方案,它們是數字型別、序列、集合和對映(以及一些此處不再討論的其他型別)。某些型別僅在語言的某些版本中可用,如下所示。

  • 布林型:內建值TrueFalse的型別。在條件表示式和需要表示某些條件真假性的任何地方都有用。大多可以與整數 1 和 0 交換使用。實際上,條件表示式將接受任何型別的數值,將布林False、整數 0 和空字串""等特殊值視為等效於False,並將所有其他值視為等效於True

數字型別

  • 整數型:整數;在 Python 2.x 中等效於 C 中的 longs,在 Python 3.x 中長度不受限制
  • 長整數型:長度不受限制的長整數;僅存在於 Python 2.x 中
  • 浮點型:浮點數,等效於 C 中的 doubles
  • 複數型:複數

序列

  • 字串型:字串;在 Python 2.x 中表示為 8 位字元序列,但在 Python 3.x 中表示為 Unicode 字元序列(範圍為 U+0000 - U+10FFFF)
  • 位元組型:0-255 範圍內的整數序列;僅在 Python 3.x 中可用
  • 位元組陣列型:與位元組型類似,但可變(見下文);僅在 Python 3.x 中可用
  • 列表型
  • 元組型

集合

  • 集合型:無序的唯一物件集合;從 Python 2.6 開始作為標準型別可用
  • 凍結集合型:與集合型類似,但不可變(見下文);從 Python 2.6 開始作為標準型別可用

對映

  • 字典型:Python 字典,也稱為雜湊表或關聯陣列,這意味著列表中的元素與一個定義相關聯,類似於Java中的 Map

其他一些,例如型別和可呼叫物件

可變物件與不可變物件

[編輯 | 編輯原始碼]

通常,Python 中的資料型別可以根據該型別物件是可變還是不可變來區分。不可變型別物件的內容在建立後不能更改。

一些不可變型別 一些可變型別
  • 整數型、浮點型、複數型
  • 字串型
  • 位元組型
  • 元組型
  • 凍結集合型
  • 布林型
  • 陣列型
  • 位元組陣列型
  • 列表型
  • 集合型
  • 字典型

只有可變物件支援原地更改物件的方法,例如重新分配序列切片,這對列表有效,但對元組和字串會引發錯誤。

重要的是要理解,Python 中的變數實際上只是記憶體中物件的引用。如果你將物件分配給變數,如下所示,

a = 1
s = 'abc'
l = ['a string', 456, ('a', 'tuple', 'inside', 'a', 'list')]

你實際上只是讓這個變數(a, s,或l)指向物件(1, 'abc', ['a string', 456, ('a', 'tuple', 'inside', 'a', 'list')]),它儲存在記憶體中的某個位置,作為一種訪問它的便捷方式。如果你重新分配變數,如下所示

a = 7
s = 'xyz'
l = ['a simpler list', 99, 10]

你讓變數指向一個不同的物件(在我們示例中是新建立的物件)。如上所述,只有可變物件才能在原地更改(l[0] = 1在我們的示例中是可以的,但s[0] = 'a'會引發錯誤)。當操作沒有明確要求原地更改時,這會變得棘手,例如+=(增量)運算子。當它用於不可變物件(如a += 1或在s += 'qwertz'中)時,Python 會默默地建立一個新物件,並將變數指向它。但是,當它用於可變物件(如l += [1,2,3]中)時,變數指向的物件將被原地更改。雖然在大多數情況下,你不需要了解這種不同的行為,但當多個變數指向同一個物件時,它就很重要。在我們的示例中,假設你設定了p = sm = l,然後s += 'etc'l += [9,8,7]。這將更改s並將p保持不變,但將同時更改ml,因為它們都指向同一個列表物件。Python 的內建id()函式,它為給定變數名返回唯一的物件識別符號,可以用來跟蹤幕後發生的事情。
通常,Python 的這種行為會導致函式中的混亂。作為說明,請考慮以下程式碼

def append_to_sequence (myseq):
    myseq += (9,9,9)
    return myseq

tuple1 = (1,2,3) # tuples are immutable
list1 = [1,2,3] # lists are mutable

tuple2 = append_to_sequence(tuple1)
list2 = append_to_sequence(list1)

print('tuple1 = ', tuple1) # outputs (1, 2, 3)
print('tuple2 = ', tuple2) # outputs (1, 2, 3, 9, 9, 9)
print('list1 = ', list1) # outputs [1, 2, 3, 9, 9, 9]
print('list2 = ', list2) # outputs [1, 2, 3, 9, 9, 9]

這將給出上面指示的,通常是意外的輸出。myseqappend_to_sequence函式的區域性變數,但當呼叫該函式時,myseq仍然會指向與我們傳入的變數(tl在我們示例中)相同的物件。如果該物件是不可變的(如元組),則沒有問題。+= 運算子將導致建立一個新的元組,並且myseq將被設定為指向它。但是,如果我們傳入可變物件的引用,該物件將在原地操作(因此myseql,在我們示例中,最終指向同一個列表物件)。

連結

建立自定義型別物件

[編輯 | 編輯原始碼]

字面量整數可以用三種方式輸入

  • 十進位制數可以直接輸入
  • 十六進位制數可以透過在前面加上 0x 或 0X 來輸入(0xff 是十六進位制 FF,或十進位制 255)
  • 八進位制字面量的格式取決於 Python 的版本
  • Python 2.x:八進位制可以透過在前面加上零 ( 0 ) 來輸入(0732 是八進位制 732,或十進位制 474)
  • Python 3.x:八進位制可以透過在前面加上零,後面跟著字母 O (0o 或 0O) 來輸入(0o732 是八進位制 732,或十進位制 474)

浮點數可以直接輸入。

長整數可以透過直接輸入(1234567891011121314151617181920 是一個長整數)或在後面追加 L (0L 是一個長整數) 來輸入。涉及短整數的溢位計算會自動轉換為長整數。

複數可以透過新增一個實數和一個虛數來輸入,虛數透過在後面追加 j 來輸入(例如 10+5j 是一個複數。10j 也是一個複數)。請注意,j 本身不構成一個數字。如果需要,請使用 1j。

字串可以是單引號或三引號字串。區別在於開始和結束分隔符,以及單引號字串不能跨越多行。單引號字串透過輸入一個單引號 (') 或一個雙引號 ("),後面跟著它的匹配項來輸入。因此

'foo' works, and
"moo" works as well,
     but
'bar" does not work, and
"baz' does not work either.
"quux'' is right out.

三引號字串類似於單引號字串,但可以跨越多行。它們的開始和結束分隔符也必須匹配。它們透過三個連續的單引號或雙引號來輸入,因此

'''foo''' works, and
"""moo""" works as well,
     but
'"'bar'"' does not work, and
"""baz''' does not work either.
'"'quux"'" is right out.

元組透過在括號中輸入,並在條目之間使用逗號來輸入

(10, 'Mary had a little lamb')

此外,當不含糊時,可以省略括號

10, 'whose fleece was as white as snow'

請注意,單元素元組可以透過將條目用括號括起來並新增逗號來輸入,如下所示

('this is a singleton tuple',)

列表類似,但使用方括號

['abc', 1,2,3]

字典透過用大括號括起來一組用冒號分隔的鍵/值對,並在其他條目之間用逗號分隔來建立

{ 'hello': 'world', 'weight': 'African or European?' }

這些複合型別中的任何一個都可以包含任何其他型別,深度不限

((((((((('bob',),['Mary', 'had', 'a', 'little', 'lamb']), { 'hello' : 'world' } ),),),),),),)

空物件

[編輯 | 編輯原始碼]

在其他程式語言中,Python 中的空指標類似於NoneNone 不是空指標或空引用,而是一個只有一個例項的實際物件。None 的一個用途是在函式的預設引數值中,有關詳細資訊,請參閱Python Programming/Functions#Default_Argument_Values。通常使用is 而不是 == 來比較None

測試 None 和賦值

if item is None:
  ...
  another = None

if not item is None:
  ...

if item is not None: # Also possible
  ...

在預設引數值中使用 None

def log(message, type = None):
  ...

PEP8 指出,“對像 None 這樣的單例的比較應始終使用 is 或 is not,絕不使用相等運算子”。因此,“if item == None:” 是不可取的。類可以重新定義相等運算子 (==),以便它的例項將等於 None。

您可以透過 dir(None) 或 id(None) 來驗證 None 是一個物件。

另請參閱Operators#Identity 章節。

連結

型別轉換

[edit | edit source]

Python 中的型別轉換示例

v1 = int(2.7) # 2
v2 = int(-3.9) # -3
v3 = int("2") # 2
v4 = int("11", 16) # 17, base 16
v5 = long(2) # Python 2.x only, not Python 3.x
v6 = float(2) # 2.0
v7 = float("2.7") # 2.7
v8 = float("2.7E-2") # 0.027
v9 = float(False) # 0.0
vA = float(True) # 1.0
vB = str(4.5) # "4.5"
vC = str([1, 3, 5]) # "[1, 3, 5]"
vD = bool(0) # False; bool fn since Python 2.2.1
vE = bool(3) # True
vF = bool([]) # False - empty list
vG = bool([False]) # True - non-empty list
vH = bool({}) # False - empty dict; same for empty tuple
vI = bool("") # False - empty string
vJ = bool(" ") # True - non-empty string
vK = bool(None) # False
vL = bool(len) # True
vM = set([1, 2])
vN = set((1, 2)) # Converts any sequence, not just a list
vO = set("abc") # {'c', 'b', 'a'}
vP = set(b"abc") # {97, 98, 99}
vQ = list(vM)
vR = list({1: "a", 2: "b"}) # dict -> list of keys
vS = tuple(vQ)
vT = list("abc") # ['a', 'b', 'c']
print(v1, v2, v3, type(v1), type(v2), type(v3))

隱式型別轉換

int1 = 4
float1 = int1 + 2.1 # 4 converted to float
# str1 = "My int:" + int1 # Error: no implicit type conversion from int to string
str1 = "My int:" + str(int1)
int2 = 4 + True # 5: bool is implicitly converted to int
float2 = 4.5 + True # 5.5: True is converted to 1, which is converted to 1.0

關鍵字:型別轉換。

連結

練習

[edit | edit source]
  1. 編寫一個程式,例項化一個單一物件,向該物件新增 [1,2],並返回結果。
    1. 找到一個返回相同長度輸出的物件(如果存在的話?)。
    2. 找到一個返回比它開始長度大 2 的輸出的物件。
    3. 找到一個導致錯誤的物件。
  2. 找到兩個資料型別 X 和 Y,使 X = X + Y 會導致錯誤,但 X += Y 不會。
華夏公益教科書