動(dòng)態(tài)且強(qiáng)類型的Python

參考自

  1. https://yunlzheng.github.io/2016/05/19/python-with-polymorphism/
  2. https://www.zhihu.com/question/19918532/answer/21645395

類型系統(tǒng)

  1. 強(qiáng)類型:偏向于不容忍隱式類型轉(zhuǎn)換。譬如說(shuō)haskell的int就不能變成double
  2. 弱類型:偏向于容忍隱式類型轉(zhuǎn)換。譬如說(shuō)C語(yǔ)言的int可以變成double
  3. 靜態(tài)類型:編譯的時(shí)候就知道每一個(gè)變量的類型,因?yàn)轭愋湾e(cuò)誤而不能做的事情是語(yǔ)法錯(cuò)誤。
  4. 動(dòng)態(tài)類型:編譯的時(shí)候不知道每一個(gè)變量的類型,因?yàn)轭愋湾e(cuò)誤而不能做的事情是運(yùn)行時(shí)錯(cuò)誤。譬如說(shuō)你不能對(duì)一個(gè)數(shù)字a寫a[10]當(dāng)數(shù)組用。

動(dòng)態(tài)且強(qiáng)類型的Python

在Python命令行中,如果我們輸入以下代碼,結(jié)果如何?

>>> variable = 1
>>> variable = '123'

上面的代碼在Python當(dāng)中是絕對(duì)合法的,那是不是意味著對(duì)象variable的類型被改變了呢?

答案是“不是”,首先variable本身并不是一個(gè)對(duì)象,它只是一個(gè)引用。
在第一行中我們創(chuàng)建了一個(gè)integer對(duì)象,并且將其綁定到variable這個(gè)名稱中,
而第二行我們創(chuàng)建了一個(gè)新的string對(duì)象,并且將其重新綁定到variable中,
當(dāng)沒(méi)有任何引用關(guān)聯(lián)到第一個(gè)integer對(duì)象那么這個(gè)對(duì)象的引用計(jì)數(shù)就會(huì)變成0,將會(huì)出發(fā)python的垃圾回收機(jī)制。

綜上所述,說(shuō)Python是動(dòng)態(tài)類型是因?yàn)槲覀冊(cè)谑褂米兞窟^(guò)程中可以不關(guān)心引用的真正類型,直到最后我們真正調(diào)用時(shí);說(shuō)Python是強(qiáng)類型,是因?yàn)樵赑ython中對(duì)象本身的類型是不可以改變的。

from random import choice
x = choice(['Hello', [1, 2, 'e', 'e']])
x.count('e')

在Python當(dāng)中我們會(huì)盡量避免使用諸如type, isinstance以及issubckass等函數(shù),因?yàn)楫?dāng)使用這個(gè)函數(shù)時(shí),會(huì)毀掉你代碼的多態(tài)性,在Python當(dāng)中真正重要的事情是關(guān)心如何讓對(duì)象按照你所希望的方式工作,不管它是否是正確的類型。

鴨子類型

當(dāng)看到一只鳥走起來(lái)像鴨子、游泳起來(lái)像鴨子、叫起來(lái)也像鴨子,那么這只鳥就可以被稱為鴨子

在鴨子類型的編程形式當(dāng)中,類型不是我們關(guān)心的第一要素,真正重要的在于這個(gè)對(duì)象的行為。

我們以靜態(tài)類型語(yǔ)言當(dāng)中的加法為例子,在靜態(tài)語(yǔ)言當(dāng)中我們通常只能對(duì)于相同類型的對(duì)象進(jìn)行加法運(yùn)算。假如使用了不同類型的對(duì)象進(jìn)行加法運(yùn)算編輯器將會(huì)直接提示錯(cuò)誤。

而在Python當(dāng)中只要對(duì)象實(shí)現(xiàn)了add方法,那么就意味著這個(gè)對(duì)象是可以進(jìn)行加法運(yùn)算的:

class A:
     def __init__(self, val):
         self.val = val
     def __add__(self, other):
         return self.__class__(self.val+other.val)
     def __str__(self):
         return str(self.val)
a = A(2)
b = A(3)
print a + b

類似于add,還包括諸如getitem setitem 等方法都是同樣的道理

a = [1,2,3]
print a[0]

等價(jià)于

print list.__getitem__(a, 0)

這里鴨子類型的產(chǎn)生是由于在Python當(dāng)中我們對(duì)a使用“索引”操作時(shí),我們并不用整整關(guān)心a的正是類型,我們只需要關(guān)心a所引用的對(duì)象是否包含getitem這樣的方法。

繼承與鴨子類型

在Java當(dāng)中我們使用接口來(lái)定義行為,通過(guò)繼承超類實(shí)現(xiàn)代碼共享。而在Python當(dāng)中由于鴨子類型的存在,除了代碼共享以外(如mixin)我們很少有對(duì)繼承的需要:

class Duck:
  def quck(self):
    print "duck qucking"
  def walk(self):
    print "duck is walking"
class GreenDuck(Duck):
  def quck(self):
    print "green duck is qucking."
class PersonWithDuckSkil:
  def quck(self):
    print "em~ i'm not a real duck"
  def walk(self):
    print "All peope can waking."
def duck_game(duck):
  duck.quck()
  duck.walk()
if __name__ == "__main__":
  duck = Duck()
  greenDuck = GreenDuck()
  people = PersonWithDuckSkil()
  duck_game(duck)
  duck_game(greenDuck)
  duck_game(people)

基于鴨子類型實(shí)現(xiàn)完全由程序員自身進(jìn)行控制,在增加了靈活性的同時(shí)還需要程序員自身的更高要求,雖然沒(méi)有語(yǔ)言層面的約束,但是還是要保持心中有“接口”的狀態(tài)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,753評(píng)論 18 399
  • http://python.jobbole.com/85231/ 關(guān)于專業(yè)技能寫完項(xiàng)目接著寫寫一名3年工作經(jīng)驗(yàn)的J...
    燕京博士閱讀 7,809評(píng)論 1 118
  • python的函數(shù)參數(shù)傳遞 看兩個(gè)例子: 所有變量都可以理解為內(nèi)存中一個(gè)對(duì)象的“引用”,或者,可以看做C中的vio...
    marvinxu閱讀 6,026評(píng)論 2 30
  • 個(gè)人筆記,方便自己查閱使用 Py.LangSpec.Contents Refs Built-in Closure ...
    freenik閱讀 67,950評(píng)論 0 5
  • 用《心》,要如何去用心呢?對(duì)于孩子我們應(yīng)該 怎樣用心陪伴?從簡(jiǎn)短的視頻中可以看出每位家長(zhǎng)對(duì)于孩子的關(guān)心和期待,。...
    點(diǎn)點(diǎn)小情緒閱讀 161評(píng)論 0 1

友情鏈接更多精彩內(nèi)容