您好,登錄后才能下訂單哦!
程序中所存儲的所有數(shù)據(jù)都是對象。每個對象都有一個身份、一個類型和一個值。對象的身份可以看作是指向它在內(nèi)存中所處位置的指針,變量名就是引用這個具體位置的名稱。
對象的類型也稱作類別,用于描述對象的內(nèi)部表示及它支持的方法與操作。創(chuàng)建特定類型的對象時,有時也將該對象稱為該類型的實例。實例被創(chuàng)建之后,它的身份和類型就不可改變。如果對象的值是可以修改的,稱為可變對象,反之稱為不變對象。如果某個對象包含對其他對象的引用,則將其稱為容器或集合。
大多數(shù)對象擁有大量特有的數(shù)據(jù)屬性和方法。屬性就是與對象相關的值。方法就是被調用時將在對象上執(zhí)行某些操作的函數(shù)。使用點"."運算符可以訪問屬性和方法。
?
內(nèi)置函數(shù)id()可返回一個對象的身份,返回值為整數(shù)。is運算符用于比較兩個對象的身份。內(nèi)置函數(shù)type()則返回一個對象的類型。例如:
def compare(a, b):
if a is b:
# 同一個對象
if a == b:
# 具有相同的值
if type(a) is type(b):
# 具有相同類型
對象的類型本身也是一個對象,稱為對象的類。所有類型對象都有一個指定的名稱,可用于執(zhí)行類型檢查,例如:
if type(s) is list:
s.append(item)
if type(d) is dict:
d.update(t)
檢查類型的更佳方式是用內(nèi)置函數(shù)isinstance(object, type),例如:
if isinstance(s, list):
s.append(item)
if isinstance(d, dict):
d.update(t)
因為isinstance()函數(shù)能夠實現(xiàn)繼承,因此是檢查所有Python對象類型的首選方式。
?
所有對象都有引用計數(shù)。無論是給對象分配一個新名稱,還是將其放入一個容器,該對象的引用計數(shù)就會增加,例如:
a = 37 # 創(chuàng)建值為37的對象
b = a # 增加37的引用計數(shù)
c = []
c.append(b) #增加37的引用計數(shù)
這個例子創(chuàng)建了一個包含值37的對象,a只是引用這個新創(chuàng)建對象的一個名稱,將a賦值給b時,b就成了同一對象的新名稱,而且該對象的引用計數(shù)會增加。類似地,將b放到一個列表中時,該對象的引用計數(shù)將再次增加。
使用del語句或者引用超出作用域時(或者被重新賦值),對象的引用計數(shù)就會減少,例如:
del a # 減少37的引用計數(shù)
b = 42 #減少37的引用計數(shù)
c[0] = 2.0 #減少37的引用計數(shù)
使用sys.getrefcount()函數(shù)可以獲得對象的當前引用計數(shù),例如:
a = 37
import sys
print(sys.getrefcount(a))
多數(shù)情況下,引用計數(shù)比猜測的要大得多,對于不可變數(shù)據(jù)(如數(shù)字和字符串),解釋器會主動在程序的不同部分共享對象,以便節(jié)約內(nèi)存。
當一個對象的引用計數(shù)歸零時,它將被垃圾收集機制處理掉。在某些情況下,很多已不再使用的對象間可能存在循環(huán)依賴關系,例如:
a = {}
b = {}
a['b'] = b
b['a'] = a
del a
del b
在以上例子中,del語句將會減少a和b的引用計數(shù),并銷毀用于引用底層對象的名稱。然而因為每個對象都包含一個對其他對象的引用,所以引用計數(shù)不會歸零,對象也不會被銷毀,從而導致內(nèi)存泄露。為了解決這個問題,解釋器會定期執(zhí)行一個循環(huán)檢測器,搜索不可訪問對象的循環(huán)并刪除它們。
?
在程序進行像a = b這樣的賦值時,就會創(chuàng)建一個對b的引用。對于像數(shù)字和字符串這樣的不可變對象,這種賦值實際上創(chuàng)建了b的一個副本。然而,對于可變對象(如列表和字典)引用行為會完全不同,例如:
a = [1, 2, 3, 4]
b = a
print(b is a) # True
b[2] = -100
print(a[2]) #-100
因為a和b引用的同一個對象,修改其中任意一個變量都會影響到另一個。所以必須創(chuàng)建對象的副本而不是新的引用。對于像列表和字典這樣的容器對象,可以使用兩種復制操作: 淺復制和深復制。淺復制將創(chuàng)建一個新對象,但它包含的是對原始對象中包含的項的引用,例如:
a = [1, 2, [3, 4]]
b = list(a)
print(b is a) #False
b.append(100)
print(b) # [1, 2, [3, 4], 100]
print(a) # [1, 2, [3, 4]]
b[2][0] = -100
print(b) # [1, 2, [-100, 4], 100]
print(a) # [1, 2, [-100, 4]]
深復制將創(chuàng)建一個新對象,并且遞歸地復制它包含的所有對象??梢允褂脴藴蕩熘械腸opy.deepcopy()函數(shù)完成該工作,例如:
import copy
a = [1, 2, [3, 4]]
b = copy.deepcopy(a)
b[2][0] = -100
print(b) # [1, 2, [-100, 4]]
print(a) # [1, 2, [3, 4]]
?
大約有12種數(shù)據(jù)類型可用于表示程序中用到的大多數(shù)數(shù)據(jù)。如下表所示:
類型分類 | 類型名稱 | 描述 |
---|---|---|
None | Type(None) | null對象None |
數(shù)字 | int | 整數(shù) |
數(shù)字 | float | 浮點數(shù) |
數(shù)字 | complex | 復數(shù) |
數(shù)字 | bool | 布爾值 |
序列 | str | 字符串 |
序列 | list | 列表 |
序列 | tuple | 元組 |
序列 | range | 創(chuàng)建的整數(shù)范圍 |
映射 | range | 創(chuàng)建的整數(shù)范圍 |
集合 | set | 可變集合 |
集合 | frozenset | 不可變集合 |
None類型表示一個沒有值的對象,在程序中表示為None。如果一個函數(shù)沒顯示返回值,則返回該對象。None常用于可選參數(shù)的默認值,以便讓函數(shù)檢測調用者是否為該參數(shù)實際傳遞了值。
Python使用4種數(shù)字類型:布爾型、整數(shù)、浮點數(shù)以及復數(shù)。除了布爾值,所有數(shù)字對象都是有符號的。所有數(shù)字類型都不可變。數(shù)字類型擁有大量的屬性和方法,可以簡化涉及混合算術的運算。為了與有理數(shù)兼容,整數(shù)使用了屬性x.numerator和x.denominator。為了兼容復數(shù),整數(shù)或浮點數(shù)y擁有屬性y.real和y.imag,以及方法y.conjugate()。使用y.as_interger_ratio()可將浮點數(shù)y轉換為分數(shù)形式的一對整數(shù)。方法y.is_interger()用于測試浮點數(shù)y是否表示整數(shù)值。通過方法y.hex()和y.fromhex()可用低級二進制形式使用浮點數(shù)。
序列表示索引為非負整數(shù)的有序對象集合,包括字符串、列表和元組。所有序列支持的方法如下表:
項目 | 描述 |
---|---|
s[i] | 返回一個序列的元素i |
s[i:j] | 返回一個切片 |
s[i:j:stride] | 返回一個擴展切片 |
lens(s) | s中的元素數(shù) |
min(s) | s中的最小值 |
max(s) | s中的最大值 |
sum(s [, initial]) | s中各項的和 |
all(s) | 檢查s中的所有項是否為True |
any(s) | 檢查s中的任意項是否為True |
適用于可變序列的方法如下表:
項目 | 描述 |
---|---|
s[i] = v | 項目賦值 |
s[i:j] = t | 切片賦值 |
s[i:j:stride] = t | 擴展切片賦值 |
del s[i] | 項目刪除 |
del s[i:j] | 切片刪除 |
del s[i:j:stride] | 擴展切片刪除 |
列表支持的方法如下表:
方法 | 描述 |
---|---|
list(s) | 將s轉換為一個列表 |
s.append(x) | 將一個新元素x追加到s末尾 |
s.extend(x) | 將一個新列表追加到s末尾 |
s.count(x) | 計算s中x的出現(xiàn)次數(shù) |
s.index(x [, start [, stop]]) | 找到x首次出現(xiàn)的位置 |
s.insert(i, x) | 在索引i處插入x |
s.pop([i]) | 返回元素i并從列表中移除它,省略i則返回列表中最后一個元素 |
s.remove(x) | 搜索x并從s中移除它 |
s.reverse() | 顛倒s中的所有元素的順序 |
s.sort([key [, reverse]]) | 對s中的所有元素進行排序。key是一個鍵函數(shù)。reverse表明以倒序對列表進行排序 |
list(s)可將任意可迭代類型轉換為列表。如果s已經(jīng)是列表,則該函數(shù)構造的新列表是s的一個淺復制。
字符串支持的方法如下表:
方法 | 描述 |
---|---|
s.captitalize() | 首字符變大寫 |
s.center(width [, pad]) | 在長度為width的字段內(nèi)將字符串居中。pad是填充字符 |
s.count(sub [, start [, end]]) | 計算指定子字符串sub的出現(xiàn)次數(shù) |
s.decode([encoding [, errors]]) | 解碼一個字符串并返回一個Unicode字符串 |
s.encdoe([encoding [, errors]]) | 返回字符串的編碼版本 |
s.endswith(suffix [, start [, end]]) | 檢查字符串是否以suffix結尾 |
s.expandtabs([tabsize]) | 使用空格替換制表符 |
s.find(sub [, start [, end]]) | 找到指定子字符串sub首次出現(xiàn)的位置,否則返回-1 |
s.format(args, *kwargs) | 格式化s |
s.index(sub [, start [, end]]) | 指到指定子字符串sub首次出現(xiàn)的位置,否則報錯 |
s.isalnum() | 檢查所有字符是否都為字母或數(shù)字 |
s.isalpha() | 檢查所有字符是否都為字母 |
s.isdigit() | 檢查所有字符是否都為數(shù)字 |
s.islower() | 檢查所有字符是否都為小寫 |
s.isspace() | 檢查所有字符是否都為空白 |
s.istitle() | 檢查字符串是否為標題字符串(每個單詞首字母大寫) |
s.isupper() | 檢查所有字符是否都為大寫 |
s.join(t) | 使用s作為分隔符連接序列t中的字符串 |
s.ljust(width [, fill]) | 在長度為width的字符串內(nèi)左對齊s |
s.lower() | 轉換為小寫形式 |
s.lstrip([chrs]) | 刪掉chrs前面的空白或字符 |
s.partition(sep) | 使用分隔符字符串sep劃分一個字符串。返回一個元組(head, sep, tail) |
s.replace(old, new [, maxreplace]) | 替換一個子字符串 |
s.rfind(sub [, start [, end]]) | 找到一個子字符串最后一次出現(xiàn)的位置 |
s.rindex(sub [, start [, end]]) | 找到一個子字符串最后一次出現(xiàn)的位置,否則報錯 |
s.rjust(width [, fill]) | 在長度為width的字符串內(nèi)右對齊s |
s.rpartition(sep) | 使用分隔符sep劃分字符串,但是從字符串的結尾處開始搜索 |
s.rsplit([sep [, maxsplit]]) | 使用sep作為分隔符對一個字符串從后往前進行劃分。maxsplit是最大劃分次數(shù) |
s.rstrip([chrs]) | 刪掉chrs尾部的空白或字符 |
s.split([sep [, maxsplit]]) | 使用sep作為分隔符對一個字符串進行劃分。maxsplit是劃分的最大次數(shù) |
s.splitlines([keepends]) | 將字符串分為一個行列表。如果keepends為1,則保留各行最后的換行符 |
s.startswith(prefix [, start [, end]]) | 檢查一個字符串是否以prefix開頭 |
s.strip([chrs]) | 刪掉chrs開頭和結尾的空白或字符 |
s.swapcase() | 將大寫轉換為小寫,或者相反 |
s.title() | 將字符串轉換為標題格式 |
s.translate(table [, deletechars]) | 使用一個字符轉換表table轉換字符串,刪除deletechars中的字符 |
s.upper() | 將一個字符串轉換為大寫形式 |
s.zfill(width) | 在字符串的左邊填充0,直至其寬度為width |
很多字符串方法都接受可選的start和end參數(shù),其值為整數(shù),用于指定s中起始和結束位置的索引。大多數(shù)情況下,這些值可以為負值,表示索引是從字符串結尾處開始計算的。
映射類型表示一個任意對象的集合,而且可以通過另一個幾乎是任意鍵值的集合進行索引。和序列不同,映射對象是無序的,可以通過數(shù)字、字符串和其他對象進行索引。映射是可變的。
字典是唯一內(nèi)置的映射類型,任何不可變對象都可以用作字典鍵值,如字符串、數(shù)字、元組等。字典的方法如下表:
項目 | 描述 |
---|---|
len(m) | 返回m中的項目數(shù) |
m[k] | 返回m中鍵k的項 |
m[k] = x | 將m[k]的值設為x |
del m[k] | 從m中刪除m[k] |
k in m | 如果k是m中的鍵,則返回True |
m.clear() | 刪除m中的所有項目 |
m.copy() | 返回m的一個副本 |
m.fromkeys(s [, value]) | 創(chuàng)建一個新字典并將序列s中的所有元素作為新字典的鍵,這些鍵的值均為value |
m.get(k [, v]) | 返回m[k],如果找不到m[k],則返回v |
m.items() | 返回由(key, value)對組成的一個序列 |
m.keys() | 返回鍵值組成的一個序列 |
m.pop(k [, default]) | 如果找到m[k],則返回m[k]并從m中刪除,否則返回default的值 |
m.popitem() | 從m中刪除一個隨機的(key, value)對,并把它返回為一個元組 |
m.setdefault(k [, v]) | 如果找到m[k],則返回m[k],不則返回v,并將m[k]的值設為v |
m.update(b) | 將b中的所有對象添加到m中 |
m.values() | 返回m中所有值的一個序列 |
集合是唯一的無序集。與序列不同,集合不提供索引或切片操作。它們和字典也有所區(qū)別,即對象不存在相關的鍵值。放入集合的項目必須是不可變的。集合分為兩種類型,set是可變的集合,而frozenset是不可變的集合,這兩類集合都是用一對內(nèi)置函數(shù)創(chuàng)建的,例如:
s = set([1, 5, 10, 15])
f = frozenset(['a', 37, 'hello'])
所有集合支持的方法如下表:
項目 | 描述 |
---|---|
len(s) | 返回s中項目數(shù) |
s.copy() | 制作s的一份副本 |
s.difference(t) | 求差集。返回所有要s中,但不在t中的項目 |
s.intersection(t) | 求交集。返回所有同時在s和t中的項目 |
s.isdisjoint(t) | 如果s和t沒有相同項,則返回True |
s.issubset(t) | 如果s是t的一個子集,則返回True |
s.issuperset(t) | 如果s是t的一個超集,則返回True |
s.symmetric_difference(t) | 求對稱差集。返回所有在s或t中,但又不同時在這兩個集合中的項 |
s.union(t) | 求并集。返回所有在s或t中的項 |
可變集合還另外提供了一些方法,如下表:
項目 | 描述 |
---|---|
s.add(item) | 將item添加到s中。如果item已經(jīng)在s中,則無任何效果 |
s.clear() | 刪除s中的所有項 |
s.difference_update(t) | 從s中刪除同時也在t中的所有項 |
s.discard(item) | 從s中刪除item,如果item不要s的成員,則無任何效果 |
s.intersection_update(t) | 計算s與t的交集,并將結果放入s |
s.pop() | 返回一個任意的集合元素,并將其從s中刪除 |
s.remove(item) | 從s中刪除item,如果item不是s的成員,引發(fā)異常 |
s.symmetric_difference_update(t) | 計算s與t的對稱差集,并將結果放入s |
s.update(t) | 將t中的所有項添加到s中 |
所有的這些操作都可以直接修改集合s。
?
在Python中,函數(shù)、類和模塊都可以當做數(shù)據(jù)操作的對象,如下表:
類型分類 | 類型名稱 | 描述 |
---|---|---|
可調用 | types.BuiltinFunctionType | 內(nèi)置函數(shù)或方法 |
可調用 | type | 內(nèi)置類型和類的類型 |
可調用 | object | 所有類型和類的祖先 |
可調用 | types.FunctionType | 用戶定義的函數(shù) |
可調用 | types.MethodType | 類方法 |
模塊 | types.ModuleType | 模塊 |
類 | object | 所有類型和類的祖先 |
類型 | type | 內(nèi)置類型和類的類型 |
可調用類型表示支持函數(shù)調用操作的對象。具有這種屬性的對象有:用戶定義的函數(shù),方法、內(nèi)置函數(shù)與方法,可調用的類與實例。
用戶定義的函數(shù)是指用def語句或lambda運算符在模塊級別上創(chuàng)建的可調用對象,它具有以下屬性:
屬性 | 描述 |
---|---|
f.__doc__ | 文檔字符串 |
f.__name__ | 函數(shù)名稱 |
f.__dict__ | 包含函數(shù)屬性的字典 |
f.__code__ | 字節(jié)編譯的代碼 |
f.__defaults__ | 包含默認參數(shù)的元組 |
f.__globals__ | 定義全局命名空間的字典 |
f.__closure__ | 包含與嵌套作用域相關數(shù)據(jù)的元組 |
方法是在類定義中定義的函數(shù)。有3種常見的方法:實例方法、類方法和靜態(tài)方法。實例方法是操作指定類的實例的方法,實例作為第一個參數(shù)傳遞給方法,根據(jù)約定該參數(shù)一般稱為self。類方法把類本身當作一個對象進行操作,在第一個參數(shù)中將類對象傳遞給類。靜態(tài)方法就是打包在類中的函數(shù),它不能使用一個實例或類對象作為第一個參數(shù)。例如:
f = Foo()
meth = f.instance_method
meth(30)
在以上例子中,meth稱為綁定方法。綁定方法是可調用對象,它封裝了函數(shù)和一個相關實例。調用綁定方法時,實例就會作為第一個參數(shù)(self)傳遞給方法。方法查找也可以出現(xiàn)類本身上,例如:
umeth = Foo.instance_method
umeth(f, 30)
在以下例子中,umeth稱為非綁定方法。非綁定方法是封裝了方法函數(shù)的可調用對象,但需要傳遞一個正確類型的實例作為第一個參數(shù)。如果傳遞的對象類型錯誤,就會引發(fā)TypeError異常。
為方法對象定義的屬性如下表:
屬性 | 描述 |
---|---|
m.__doc__ | 文檔字符串 |
m.__name__ | 方法名稱 |
m.__class__ | 定義該方法的類 |
m.__func__ | 實現(xiàn)方法的函數(shù)對象 |
m.__self__ | 與方法相關的實例(如果是非綁定方法則為None) |
類對象和實例也可以當作可調用對象進行操作。類對象使用class語句創(chuàng)建,并作為函數(shù)調用,以創(chuàng)建新實例。在這種情況下,將函數(shù)的參數(shù)傳遞給類的__init__()方法,以便初始化新創(chuàng)建的實例。如果實例定義了一個特殊方法__call__(),它就能夠模擬函數(shù)的行為。如果該方法是為某個實例x而定義,使用x(args)語句等同于調用方法x.__call__(args)。
定義類時,類定義通常會生成一個type類型的對象,一個類型對象t的常用屬性如下表:
屬性 | 描述 |
---|---|
t.__doc__ | 文檔字符串 |
t.__name__ | 類名稱 |
t.__bases__ | 基類的元組 |
t.__dict__ | 保存類方法和變量的字典 |
t.__module__ | 定義類的模塊名稱 |
t.__abstractmethods__ | 抽象方法名稱的集合 |
創(chuàng)建一個對象實例時,實例的類型就是定義它的類,例如:
f = Foo()
print(type(f)) # <class '__main__.Foo'>
下表顯示實例擁有的特殊屬性:
屬性 | 描述 |
---|---|
t.__class__ | 實例所屬的類 |
t.__dict__ | 保存實例數(shù)據(jù)的字典 |
模塊類型是一個容器,可保存使用import語句加載的對象。模塊定義了一個使用字典實現(xiàn)的命名空間,比如,m.x=y等價于m.__dic__["x"]=y。模塊的可用屬性如下:
屬性 | 描述 |
---|---|
m.__dict__ | 與模塊相關的字典 |
m.__doc__ | 模塊文檔字符串 |
m.__name__ | 模塊名稱 |
m.__file__ | 用于加載模塊的文件 |
m.__path__ | 完全限定包名,只在模塊對象引用包時定義 |
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。