python檢視物件的方法 獲取物件資訊

2021-10-11 20:34:27 字數 4403 閱讀 2356

當我們拿到乙個物件的引用時,如何知道這個物件是什麼型別、有哪些方法呢?

使用type()

首先,我們來判斷物件型別,使用type()函式:

基本型別都可以用type()判斷:

>>> type(123)

>>> type('str')

>>> type(none)

如果乙個變數指向函式或者類,也可以用type()判斷:

>>> type(abs)

>>> type(a)

但是type()函式返回的是什麼型別呢?它返回對應的class型別。如果我們要在if語句中判斷,就需要比較兩個變數的type型別是否相同:

>>> type(123)==type(456)

true

>>> type(123)==int

true

>>> type('abc')==type('123')

true

>>> type('abc')==str

true

>>> type('abc')==type(123)

false

判斷基本資料型別可以直接寫int,str等,但如果要判斷乙個物件是否是函式怎麼辦?可以使用types模組中定義的常量:

>>> import types

>>> def fn():

... pass

>>> type(fn)==types.functiontype

true

>>> type(abs)==types.builtinfunctiontype

true

>>> type(lambda x: x)==types.lambdatype

true

>>> type((x for x in range(10)))==types.generatortype

true

使用isinstance()

對於class的繼承關係來說,使用type()就很不方便。我們要判斷class的型別,可以使用isinstance()函式。

我們回顧上次的例子,如果繼承關係是:

object -> animal -> dog -> husky

那麼,isinstance()就可以告訴我們,乙個物件是否是某種型別。先建立3種型別的物件:

>>> a = animal()

>>> d = dog()

>>> h = husky()

然後,判斷:

>>> isinstance(h, husky)

true

沒有問題,因為h變數指向的就是husky物件。

再判斷:

>>> isinstance(h, dog)

true

h雖然自身是husky型別,但由於husky是從dog繼承下來的,所以,h也還是dog型別。換句話說,isinstance()判斷的是乙個物件是否是該型別本身,或者位於該型別的父繼承鏈上。

因此,我們可以確信,h還是animal型別:

>>> isinstance(h, animal)

true

同理,實際型別是dog的d也是animal型別:

>>> isinstance(d, dog) and isinstance(d, animal)

true

但是,d不是husky型別:

>>> isinstance(d, husky)

false

能用type()判斷的基本型別也可以用isinstance()判斷:

>>> isinstance('a', str)

true

>>> isinstance(123, int)

true

>>> isinstance(b'a', bytes)

true

並且還可以判斷乙個變數是否是某些型別中的一種,比如下面的**就可以判斷是否是list或者tuple:

>>> isinstance([1, 2, 3], (list, tuple))

true

>>> isinstance((1, 2, 3), (list, tuple))

true

總是優先使用isinstance()判斷型別,可以將指定型別及其子類「一網打盡」。

使用dir()

如果要獲得乙個物件的所有屬性和方法,可以使用dir()函式,它返回乙個包含字串的list,比如,獲得乙個str物件的所有屬性和方法:

>>> dir('abc')

['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']

類似__***__的屬性和方法在python中都是有特殊用途的,比如__len__方法返回長度。在python中,如果你呼叫len()函式試圖獲取乙個物件的長度,實際上,在len()函式內部,它自動去呼叫該物件的__len__()方法,所以,下面的**是等價的:

>>> len('abc')

>>> 'abc'.__len__()

我們自己寫的類,如果也想用len(myobj)的話,就自己寫乙個__len__()方法:

>>> class mydog(object):

... def __len__(self):

... return 100

>>> dog = mydog()

>>> len(dog)

剩下的都是普通屬性或方法,比如lower()返回小寫的字串:

>>> 'abc'.lower()

'abc'

僅僅把屬性和方法列出來是不夠的,配合getattr()、setattr()以及hasattr(),我們可以直接操作乙個物件的狀態:

>>> class myobject(object):

... def __init__(self):

... self.x = 9

... def power(self):

... return self.x * self.x

>>> obj = myobject()

緊接著,可以測試該物件的屬性:

>>> hasattr(obj, 'x') # 有屬性'x'嗎?

true

>>> obj.x

>>> hasattr(obj, 'y') # 有屬性'y'嗎?

false

>>> setattr(obj, 'y', 19) # 設定乙個屬性'y'

>>> hasattr(obj, 'y') # 有屬性'y'嗎?

true

>>> getattr(obj, 'y') # 獲取屬性'y'

>>> obj.y # 獲取屬性'y'

如果試圖獲取不存在的屬性,會丟擲attributeerror的錯誤:

>>> getattr(obj, 'z') # 獲取屬性'z'

traceback (most recent call last):

file "", line 1, in

attributeerror: 'myobject' object has no attribute 'z'

可以傳入乙個default引數,如果屬性不存在,就返回預設值:

>>> getattr(obj, 'z', 404) # 獲取屬性'z',如果不存在,返回預設值404

也可以獲得物件的方法:

>>> hasattr(obj, 'power') # 有屬性'power'嗎?

true

>>> getattr(obj, 'power') # 獲取屬性'power'

>>> fn = getattr(obj, 'power') # 獲取屬性'power'並賦值到變數fn

>>> fn # fn指向obj.power

>>> fn() # 呼叫fn()與呼叫obj.power()是一樣的

小結通過內建的一系列函式,我們可以對任意乙個python物件進行剖析,拿到其內部的資料。要注意的是,只有在不知道物件資訊的時候,我們才會去獲取物件資訊。如果可以直接寫:

sum = obj.x + obj.y

就不要寫:

sum = getattr(obj, 'x') + getattr(obj, 'y')

乙個正確的用法的例子如下:

def readimage(fp):

if hasattr(fp, 'read'):

return readdata(fp)

return none

假設我們希望從檔案流fp中讀取影象,我們首先要判斷該fp物件是否存在read方法,如果存在,則該物件是乙個流,如果不存在,則無法讀取。hasattr()就派上了用場。

請注意,在python這類動態語言中,根據鴨子型別,有read()方法,不代表該fp物件就是乙個檔案流,它也可能是網路流,也可能是記憶體中的乙個位元組流,但只要read()方法返回的是有效的影象資料,就不影響讀取影象的功能。

參考原始碼

python 獲取物件資訊的方法

1 type 返回對應的class型別 例如 type 123 type 456 true type 123 int true type abc type 123 true type abc str true type abc type 123 false 2 isinstance 對於class的...

獲取節點物件的方法

var odiv document.queryselector div 1,獲取當前標籤中所有的子級節點 執行結果,是乙個偽陣列,可以foreach 形式是與 queryselectorall 獲取的偽陣列是一樣的 console.log odiv.childnodes 2,獲取當前標籤中,所有的元...

python 獲取物件 python中獲取物件資訊

拿到乙個變數,除了用 isinstance 判斷它是否是某種型別的例項外,還有沒有別的方法獲取到更多的資訊呢?例如,已有定義 class person object def init self,name,gender self.name name self.gender gender class s...