python判斷變數資料型別時,建議使用isinstance()方法代替type(). 進行型別檢查首先想到的就是用type(),但是Type在某些特定情況下判斷型別存在問題,今天就來說下type在python型別判斷時的坑。
type()方法
例子: int型別判斷
>>> import types >>> type(2017)==types.IntType True
Python2.7中的types型別:
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
Python3.x中的types型別:
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
Python3.x進行了型別的精簡
isinstance方法
isinstance(object, classinfo)
object表示例項,classinfo可以是直接或間接類名、基本型別或者有它們組成的元組。
基本用法
>>> isinstance(1, int) True >>> >>> isinstance('pythontab.com', (str, int)) # 是其中一種即可 True >>> isinstance(100, (str, int)) # 是其中一種即可 True
上面type的例子可以表示為:
>>> import types >>> isinstance(2017,int) True
那為什麼不推薦使用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 ca: pass class cb: pass a = ca() b = cb() print (type(a) is type(b))
程式碼的輸出結果: True
注意: 這個例子僅僅針對Python2.x版本, Python3.x版本中會返回Flase,不存在該問題
type比較的結果a和b的型別是一樣的,結果明顯是不準確的。在old-style class中,任意instance的type都是'instance'。所以絕對不能用type來判斷其型別。
另外這個問題又與Python的思想有關,正常情況下不應該編寫程式碼檢查型別的,而應該直接假設被操作的instance具有你希望的屬性,否則丟擲異常。即使需要檢查型別,也應該用isinstance來判斷,這樣你期望型別的subclass也能正常被處理(比如,一個函式需要處理Message型別,那麼它應該也能處理Message的子型別MyMessage,所以應該使用isinstance(arg,Message)這樣來判斷而不是type(arg) == Message來判斷)
結論:
儘量不要使用type()方法,多使用isinstance(),這樣可以減少錯誤。