天天看點

比較type和isinstance

Python是一種動态語言,比如建立一個變量,一開始引用的是字元串,随後就可以再引用整數或者浮點數,解釋器對這種變換也接受。這與類似Java那樣的語言就完全不同了。

name = "Sebastian"
# 下面示範的就是動态語言特點
name = 42
name = None
name = Exception()    # 引用一個執行個體對象
           

複制

在程式中,檢查變量所引用的對象是什麼類型,對于Python程式也是必要的。一般我們會實用

type()

或者

isinstance()

這兩個内置函數。

>>> variable = "hello"
>>> type(variable) is str
True
>>> isinstance(variable, str)
True
           

複制

下面比較一下這兩個函數的性能:

$ python -m timeit -s "variable = 'hello'" "type(variable) is int"
2000000 loops, best of 5: 102 nsec per loop
$ python -m timeit -s "variable = 'hello'" "isinstance(variable, str)"
5000000 loops, best of 5: 72.8 nsec per loop
           

複制

type

instance

慢了 40% (102/72.8 = 1.40).

有人也實用

type(variable) == str

種方式判斷某個對象的類型,雖然此方法是可行的,但不提倡,因為:

• == should be used when you want to check the value of a variable. We would use it to see if the value ofvariable is equal to "hello". But when we want to check if variable is a string, is operator is more appropriate. For a more detailed explanation of when to use one or the other, check this article. • == is slower:

  • ==

    應該用于檢查對象是否與另外一個對象相等。我們可以用它來檢視變量的值是否等于

    hello

    ,但是想要檢查變量是否是一個字元串時,不要用這個符号,而是改用

    is

    操作符更合适。
  • ==

    的執行速度更慢,可以用下面的代碼檢驗:
$ python -m timeit -s "variable = 'hello'" "type(variable) == str"
2000000 loops, best of 5: 114 nsec per loop
           

複制

isinstance

type

之間除了前面示範的執行速度不同之外,還有别的差別嗎?

有!而且下面要說的差別,比執行速度還重要。

  • type

    的傳回值是一個對象的類型(類),可以用它來檢查

    variable

    的類型是否為

    str

  • isinstance

    要檢查第一個參數對象是不是第二個參數所指定的類的執行個體,例如

    variable

    str

    類的一個執行個體嗎?或者,檢查是不是第二個參數所指定的類的子類的示例,例如

    variable

    str

    子類的一個執行個體嗎?

這在實踐很有用。假設自定義一個類,它類似于清單,但方法可以更多一些。是以我們可以把

list

作為這個類的父類,然後在這個類裡面寫其他的方法,基本樣式如下:

class MyAwesomeList(list):
    # Add additional functions here
           

複制

但是現在,如果我們将這個新類與一個清單進行比較,

type

isinstance

會傳回不同的結果!

>>> my_list = MyAwesomeList()
>>> type(my_list) is list
False
>>> isinstance(my_list, list)
True
           

複制

輸出結果不同。

isinstance

檢查

my_list

是否是

list

的一個執行個體(它不是)、或者是否是

list

的一個子類的執行個體(它是,因為

MyAwesomeList

list

的一個子類)。這個細節,有時候會導緻BUG。

isinstance

通常是判斷對象類型的首選方法。它不僅更快,而且還考慮了繼承,這通常是我們所需要的。不過,在Python中,我們通常不需要檢查某個對象的類型,隻需要關注它能不能具備像字元串或清單那樣的方法和屬性,這就是著名的“鴨子檢驗”。是以,隻需要使用

isinstance

即可。

另一方面,如果想顯式地檢查給定對象是否屬于某一特定類型(而不是它的子類),可以使用

type

,但通常用這樣的語句

type(var) is some_type

,而不是

type(var) == some_type

記住,編寫函數的時候,不檢查對象類型,是Python的慣例,不要把Java的習慣帶過來。