Python中爲什麼推薦使用isinstance來進行類型判斷?而不是type

Python在定義變量的時候不用指明具體的的類型,解釋器會在運行的時候會自動檢查 變量的類型,並根據需要進行隱式的類型轉化。因爲Python是動態語言,所以一般情 況下是不推薦進行類型轉化的。比如"+"操作時,如果加號兩邊是數據就進行加法操 作,如果兩邊是字符串就進行字符串連接操作,如果兩邊是列表就進行合併操作,甚 至可以進行復數的運算。解釋器會在運行時根據兩邊的變量的類型調用不同的內部方法。 當加號兩邊的變量類型不一樣的時候,又不能進行類型轉化,就會拋出TypeError的異常。

但是在實際的開發中,爲了提高代碼的健壯性,我們還是需要進行類型檢查的。而進行 類型檢查首先想到的就是用type(),比如使用type判斷一個int類型。

import types
if type(1) is types.Integer:
    print('1是int類型')
else:
    print('1不是int類型')

上面的程序會輸出:1是int類型

我們在types中可以找到一些常用的類型,在2.7.6中顯示的結果:

types.BooleanType              #  bool類型
types.BufferType               #  buffer類型
types.BuiltinFunctionType      #  內建函數,比如len()
types.BuiltinMethodType        #  內建方法,指的是類中的方法
types.ClassType                #  類類型
types.CodeType                 #  代碼塊類型
types.ComplexType              #  複數類型
types.DictProxyType            #  字典代理類型
types.DictType                 #  字典類型
types.DictionaryType           #  字典備用的類型
types.EllipsisType
types.FileType                 #  文件類型
types.FloatType                #  浮點類型
types.FrameType
types.FunctionType             #  函數類型
types.GeneratorType       
types.GetSetDescriptorType
types.InstanceType             #  實例類型
types.IntType                  #  int類型
types.LambdaType               #  lambda類型
types.ListType                 #  列表類型
types.LongType                 #  long類型
types.MemberDescriptorType
types.MethodType               #  方法類型
types.ModuleType               #  module類型
types.NoneType                 #  None類型
types.NotImplementedType
types.ObjectType               #  object類型
types.SliceTypeh
types.StringType               #  字符串類型
types.StringTypes     
types.TracebackType   
types.TupleType                #  元組類型
types.TypeType                 #  類型本身
types.UnboundMethodType
types.UnicodeType    
types.XRangeType

在Python 3中,類型已經明顯減少了很多

types.BuiltinFunctionType
types.BuiltinMethodType
types.CodeType
types.DynamicClassAttribute
types.FrameType
types.FunctionType
types.GeneratorType
types.GetSetDescriptorType
types.LambdaType
types.MappingProxyType
types.MemberDescriptorType
types.MethodType
types.ModuleType
types.SimpleNamespace
types.TracebackType
types.new_class
types.prepare_class

但是我們並不推薦使用type來進行類型檢查,之所以把這些類型列出來,也是爲了擴展知識面。那爲什麼不推薦使用type進行類型檢查呢?我們來看一下下面的例子。

import types
class UserInt(int):
    def __init__(self, val=0):
        self.val = int(val)

i = 1
n = UserInt(2)
print(type(i) is type(n))

上面的代碼輸出:False

這就說明i和n的類型是不一樣的,而實際上UserInt是繼承自int的,所以這個判斷是存在問題的, 當我們對Python內建類型進行擴展的時候,type返回的結果就不夠準確了。我們再看一個例子。

class A():
    pass

class B():
    pass

a = A()
b = B()

print(type(a) is type(b))

代碼的輸出結果: True

type比較的結果a和b的類型是一樣的,結果明顯是不準確的。這種古典類的實例,type返回的結果都 是一樣的,而這樣的結果不是我們想要的。對於內建的基本類型來說,使用tpye來檢查是沒有問題的, 可是當應用到其他場合的時候,type就顯得不可靠了。這個時候我們就需要使用isinstance來進行類型檢查。

isinstance(object, classinfo)

object表示實例,classinfo可以是直接或間接類名、基本類型或者由它們組成的元組。

>>> isinstance(2, float)
False
>>> isinstance('a', (str, unicode))
True
>>> isinstance((2, 3), (str, list, tuple))
True
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章