從一個(gè)低級(jí)錯(cuò)誤說(shuō)起,動(dòng)態(tài)語(yǔ)言和靜態(tài)語(yǔ)言

先從一個(gè)低級(jí)錯(cuò)誤說(shuō)起

上周茶敏,在項(xiàng)目中使用SQLAchemy操作數(shù)據(jù)庫(kù)時(shí)壤靶,代碼中出現(xiàn)了數(shù)據(jù)修改操作無(wú)法寫(xiě)入數(shù)據(jù)庫(kù)的bug。為簡(jiǎn)化問(wèn)題惊搏,就不貼原本的代碼了贮乳,代碼邏輯結(jié)構(gòu)大致如下:

try:
      results = db.session.query(all_record).all()
      for result in results:
            result.nmae = 'new name'
            print(result.nmae)
      db.session.commit()
except Exception as e:
      print(e)

執(zhí)行結(jié)果:

new name

大家知道,SQLAchemy是Python的一個(gè)用于實(shí)現(xiàn)ORM庫(kù)(Object Relational Mapping恬惯,即對(duì)象關(guān)系映射)向拆,我們可以藉由它通過(guò)編程語(yǔ)言對(duì)多種類型的數(shù)據(jù)庫(kù)實(shí)現(xiàn)數(shù)據(jù)表定義創(chuàng)建和對(duì)數(shù)據(jù)的增刪改查。它將數(shù)據(jù)庫(kù)中的關(guān)系轉(zhuǎn)化為程序語(yǔ)言中的對(duì)象酪耳,因此所有對(duì)數(shù)據(jù)庫(kù)的操作都體現(xiàn)為對(duì)對(duì)象屬性的修改浓恳。
然而這段代碼執(zhí)行完后,并沒(méi)有將數(shù)據(jù)寫(xiě)入數(shù)據(jù)表的對(duì)應(yīng)字段,這種情況一般來(lái)說(shuō)是沒(méi)有執(zhí)行commit提交事務(wù)奖蔓,導(dǎo)致數(shù)據(jù)修改的結(jié)果并沒(méi)有真正寫(xiě)入數(shù)據(jù)庫(kù)赞草。
但是在這里,我是明明寫(xiě)了commit()語(yǔ)句并且用斷點(diǎn)的方式檢查卻是執(zhí)行了的吆鹤,而且也沒(méi)有拋出異常厨疙。
排除了許多可能后,我才猛然發(fā)現(xiàn)疑务,犯了一個(gè)寫(xiě)錯(cuò)變量名的低級(jí)錯(cuò)誤沾凄。比如,這里代碼操作的屬性是 result.nmae 知允,在數(shù)據(jù)庫(kù)中定義的本應(yīng)該是name撒蟀,在對(duì)象所對(duì)應(yīng)的類里的屬性自然也是name,故而在寫(xiě)入的時(shí)候沒(méi)有相應(yīng)字段可以寫(xiě)入温鸽,所以我去數(shù)據(jù)庫(kù)查看name依然是以前的值保屯。可是它也沒(méi)有拋出異常涤垫,這個(gè)大概就是SQLAchemy的坑了姑尺。
但是,問(wèn)題就來(lái)了蝠猬,既然類中沒(méi)有nmae這個(gè)屬性切蟋,為什么可以被定義和賦值?
這似乎顛覆了我對(duì)面向?qū)ο蟮恼J(rèn)知榆芦。經(jīng)某大牛同學(xué)Talk is cheap 柄粹,Show me the code式的點(diǎn)播,我才猛然認(rèn)識(shí)到這是Python作為一門(mén)動(dòng)態(tài)語(yǔ)言的特性匆绣。

大牛code如下:

In [16]: class test:
    ...:     def __init__(self):
    ...:         self.A = 1
    ...:
    ...:

In [17]: t = test()

In [18]: t.A
Out[18]: 1

In [19]: t.B = 2

In [20]: t.__dict__
Out[20]: {'A': 1, 'B': 2}

In [21]: t.B
Out[21]: 2

Python類由類變量和實(shí)例變量驻右、方法以及可以看作特殊變量的數(shù)據(jù)成員(類變量或者實(shí)例變量, 用于處理類及其實(shí)例對(duì)象的相關(guān)的數(shù)據(jù))構(gòu)成。其中犬绒,類變量為所有類產(chǎn)生實(shí)例所共用旺入,比如一個(gè)類對(duì)應(yīng)的實(shí)例個(gè)數(shù)的計(jì)數(shù)器。想要修改類變量凯力,必須通過(guò)類內(nèi)部特定的修改方法來(lái)修改茵瘾。而作為實(shí)例變量,直接像上面那樣咐鹤,在實(shí)例化后賦值即可拗秘,甚至也可以定義一個(gè)類中不存在的新的對(duì)象屬性。作為一個(gè)從JAVA入門(mén)面向?qū)ο蟮某绦騿T來(lái)說(shuō)祈惶,卻是有些難以理解雕旨,因?yàn)镴AVA并沒(méi)有這種常規(guī)操作扮匠,javassit這種非常規(guī)技術(shù)就不說(shuō)了。
造成這種差異和誤解的根本原因是JAVA是一門(mén)靜態(tài)語(yǔ)言凡涩,而Python是一門(mén)動(dòng)態(tài)語(yǔ)言棒搜。而恰好,JAVA又是一門(mén)編譯型的語(yǔ)言活箕,而Python是一個(gè)用解釋器執(zhí)行的解釋型語(yǔ)言力麸。于是有人告訴我,編譯型語(yǔ)言就是靜態(tài)語(yǔ)言育韩,而解釋型語(yǔ)言就是動(dòng)態(tài)語(yǔ)言克蚂。
事實(shí)果真如此么?我們一起來(lái)梳理下面幾個(gè)概念筋讨!

編譯型語(yǔ)言

需通過(guò)編譯器(compiler)將源代碼編譯成機(jī)器碼埃叭,之后才能執(zhí)行的語(yǔ)言。一般需經(jīng)過(guò)編譯(compile)悉罕、鏈接(linker)這兩個(gè)步驟赤屋。編譯是把源代碼編譯成機(jī)器碼,鏈接是把各個(gè)模塊的機(jī)器碼和依賴庫(kù)串連起來(lái)生成可執(zhí)行文件蛮粮。

  • 優(yōu)點(diǎn):一次編譯益缎,重復(fù)可用,不需要每次執(zhí)行時(shí)再編譯一遍然想,由于編譯后生成的是能直接被機(jī)器執(zhí)行的機(jī)器碼,所以通常情況下執(zhí)行效率會(huì)更高欣范。
  • 缺點(diǎn):編譯之后如果需要修改就需要整個(gè)模塊重新編譯变泄。編譯的時(shí)候根據(jù)對(duì)應(yīng)的運(yùn)行環(huán)境生成機(jī)器碼,不同的操作系統(tǒng)之間移植就會(huì)有問(wèn)題恼琼,需要根據(jù)運(yùn)行的操作系統(tǒng)環(huán)境編譯不同的可執(zhí)行文件(比如Windows上的.exe文件妨蛹,CentOS上的.rpm文件)。
  • 代表語(yǔ)言:C晴竞、C++蛙卤、Pascal、Object-C以及最近很火的蘋(píng)果新語(yǔ)言swift

解釋型語(yǔ)言

解釋性語(yǔ)言的程序不需要編譯噩死,相比編譯型語(yǔ)言省了道工序颤难,解釋性語(yǔ)言在運(yùn)行程序的時(shí)候才逐行翻譯為機(jī)器碼來(lái)給機(jī)器執(zhí)行。

  • 優(yōu)點(diǎn):可以在任何安裝了解釋器(虛擬機(jī))的機(jī)器上運(yùn)行已维,不用關(guān)心用了什么操作系統(tǒng)行嗤。靈活,修改代碼的時(shí)候直接修改就可以垛耳,可以快速部署栅屏,不用停機(jī)維護(hù)飘千。
  • 缺點(diǎn):每次運(yùn)行的時(shí)候都要解釋一遍,性能上不如編譯型語(yǔ)言栈雳。
  • 代表語(yǔ)言:JavaScript护奈、Python、Erlang哥纫、PHP逆济、Perl、Ruby

混合型語(yǔ)言

既然編譯型和解釋型各有缺點(diǎn)就會(huì)有人想到把兩種類型整合起來(lái)磺箕,取其精華去其糟粕奖慌。就出現(xiàn)了半編譯型語(yǔ)言。比如C#,C#在編譯的時(shí)候不是直接編譯成機(jī)器碼而是中間碼松靡,.NET平臺(tái)提供了中間語(yǔ)言運(yùn)行庫(kù)運(yùn)行中間碼简僧,中間語(yǔ)言運(yùn)行庫(kù)類似于Java虛擬機(jī)。.net在編譯成IL代碼后雕欺,保存在dll中岛马,首次運(yùn)行時(shí)由JIT在編譯成機(jī)器碼緩存在內(nèi)存中,下次直接執(zhí)行屠列。Java先生成字節(jié)碼再在Java虛擬機(jī)中解釋執(zhí)行啦逆。嚴(yán)格來(lái)說(shuō)混合型語(yǔ)言屬于解釋型語(yǔ)言。C#更接近編譯型語(yǔ)言笛洛。

動(dòng)態(tài)語(yǔ)言和靜態(tài)語(yǔ)言

動(dòng)態(tài)語(yǔ)言

是一類在運(yùn)行時(shí)可以改變其結(jié)構(gòu)的語(yǔ)言:例如新的函數(shù)夏志、對(duì)象、甚至代碼可以被引進(jìn)苛让,已有的函數(shù)可以被刪除或是其他結(jié)構(gòu)上的變化沟蔑。通俗點(diǎn)說(shuō)就是在運(yùn)行時(shí)代碼可以根據(jù)某些條件改變自身結(jié)構(gòu)。
主要?jiǎng)討B(tài)語(yǔ)言:Object-C狱杰、C#瘦材、JavaScript、PHP仿畸、Python食棕、Erlang。

靜態(tài)語(yǔ)言

與動(dòng)態(tài)語(yǔ)言相對(duì)應(yīng)的错沽,運(yùn)行時(shí)結(jié)構(gòu)不可變的語(yǔ)言就是靜態(tài)語(yǔ)言簿晓。如Java、C甥捺、C++抢蚀。

走出誤區(qū)

很多人認(rèn)為解釋型語(yǔ)言都是動(dòng)態(tài)語(yǔ)言,這個(gè)觀點(diǎn)是錯(cuò)的镰禾!Java是解釋型語(yǔ)言但是不是動(dòng)態(tài)語(yǔ)言皿曲,Java不能在運(yùn)行的時(shí)候改變自己結(jié)構(gòu)唱逢。反之成立嗎?動(dòng)態(tài)語(yǔ)言都是解釋型語(yǔ)言屋休。也是錯(cuò)的坞古!Object-C是編譯型語(yǔ)言,但是他是動(dòng)態(tài)語(yǔ)言劫樟。得益于特有的run time機(jī)制(準(zhǔn)確說(shuō)run time不是語(yǔ)法特性是運(yùn)行時(shí)環(huán)境痪枫,這里不展開(kāi))OC代碼是可以在運(yùn)行的時(shí)候插入、替換方法的叠艳。

靜態(tài)類型語(yǔ)言和動(dòng)態(tài)類型語(yǔ)言

為了不混淆動(dòng)態(tài)語(yǔ)言和動(dòng)態(tài)類型語(yǔ)言奶陈,下面還補(bǔ)充說(shuō)明以下幾個(gè)概念

動(dòng)態(tài)類型語(yǔ)言

很多網(wǎng)上資料把動(dòng)態(tài)類型語(yǔ)言和動(dòng)態(tài)語(yǔ)言混為一談,簡(jiǎn)直是誤人子弟附较。動(dòng)態(tài)類型語(yǔ)言和動(dòng)態(tài)語(yǔ)言是完全不同的兩個(gè)概念吃粒。動(dòng)態(tài)類型語(yǔ)言是指在運(yùn)行期間才去做數(shù)據(jù)類型檢查的語(yǔ)言,說(shuō)的是數(shù)據(jù)類型拒课,動(dòng)態(tài)語(yǔ)言說(shuō)的是運(yùn)行是改變結(jié)構(gòu)徐勃,說(shuō)的是代碼結(jié)構(gòu)。
動(dòng)態(tài)類型語(yǔ)言的數(shù)據(jù)類型不是在編譯階段決定的早像,而是把類型綁定延后到了運(yùn)行階段僻肖。
主要語(yǔ)言:Python、Ruby卢鹦、Erlang臀脏、JavaScript、swift法挨、PHP谁榜、Perl。

靜態(tài)類型語(yǔ)言

靜態(tài)語(yǔ)言的數(shù)據(jù)類型是在編譯其間確定的或者說(shuō)運(yùn)行之前確定的凡纳,編寫(xiě)代碼的時(shí)候要明確確定變量的數(shù)據(jù)類型。
主要語(yǔ)言:C帝蒿、C++荐糜、C#、Java葛超、Object-C暴氏。

注意

解釋型語(yǔ)言并不都是動(dòng)態(tài)類型語(yǔ)言,編譯型語(yǔ)言也不全是靜態(tài)類型語(yǔ)言绣张。swift是編譯型語(yǔ)言但是它也是動(dòng)態(tài)類型語(yǔ)言答渔。C#和Java是解釋型語(yǔ)言也是靜態(tài)類型語(yǔ)言,雖然它們看作解釋型語(yǔ)言侥涵,但是它們也有編譯過(guò)程沼撕,會(huì)在編譯過(guò)程中做數(shù)據(jù)類型的檢查
所以宋雏,動(dòng)態(tài)類型語(yǔ)言是數(shù)據(jù)類型檢查的動(dòng)態(tài)(運(yùn)行時(shí)檢查),而不是像動(dòng)態(tài)語(yǔ)言一樣代碼邏輯結(jié)構(gòu)的在運(yùn)行時(shí)可變更务豺,靜態(tài)則相反磨总。

強(qiáng)類型語(yǔ)言和弱類型語(yǔ)言

說(shuō)到數(shù)據(jù)類型,就不得不提從數(shù)據(jù)類型是否嚴(yán)格定義的角度產(chǎn)生的另外兩個(gè)概念:強(qiáng)類型語(yǔ)言和弱類型語(yǔ)言

強(qiáng)類型語(yǔ)言:

強(qiáng)類型語(yǔ)言笼沥,一旦一個(gè)變量被指定了某個(gè)數(shù)據(jù)類型蚪燕,如果不經(jīng)過(guò)強(qiáng)制類型轉(zhuǎn)換,那么它就永遠(yuǎn)是這個(gè)數(shù)據(jù)類型奔浅。你不能把一個(gè)整形變量當(dāng)成一個(gè)字符串來(lái)處理馆纳。
主要語(yǔ)言:Java、C#汹桦、Python鲁驶、Object-C、Ruby

弱類型語(yǔ)言:

數(shù)據(jù)類型可以被忽略营勤,一個(gè)變量可以賦不同數(shù)據(jù)類型的值灵嫌。一旦給一個(gè)整型變量a賦一個(gè)字符串值,那么a就變成字符類型葛作。
主要語(yǔ)言:JavaScript寿羞、PHP

3、注意:

一個(gè)語(yǔ)言是不是強(qiáng)類型語(yǔ)言和是不是動(dòng)態(tài)類型語(yǔ)言也沒(méi)有必然聯(lián)系赂蠢。Python是動(dòng)態(tài)類型語(yǔ)言绪穆,是強(qiáng)類型語(yǔ)言。JavaScript是動(dòng)態(tài)類型語(yǔ)言虱岂,是弱類型語(yǔ)言玖院。Java是靜態(tài)類型語(yǔ)言,是強(qiáng)類型語(yǔ)言第岖。

附錄概念對(duì)照表

概念 劃分角度 特點(diǎn)
編譯型語(yǔ)言 執(zhí)行方式 將源代碼編譯為機(jī)器碼給機(jī)器執(zhí)行
解釋型語(yǔ)言 執(zhí)行方式 將源代碼交由解釋器解釋為機(jī)器碼執(zhí)行
混合型語(yǔ)言 執(zhí)行方式 將源代碼編譯為“中間碼”难菌,再交由解釋器(虛擬機(jī))解釋為機(jī)器碼執(zhí)行
動(dòng)態(tài)語(yǔ)言 代碼邏輯結(jié)構(gòu)是否可以在運(yùn)行時(shí)改變 可以改變
靜態(tài)語(yǔ)言 代碼邏輯結(jié)構(gòu)是否可以在運(yùn)行時(shí)改變 不可改變
動(dòng)態(tài)類型語(yǔ)言 代碼的數(shù)據(jù)類型何時(shí)檢查 運(yùn)行時(shí)檢查
靜態(tài)類型語(yǔ)言 代碼的數(shù)據(jù)類型何時(shí)檢查 運(yùn)行時(shí)不檢查
強(qiáng)類型語(yǔ)言 變量定義后是否可以隨意改變數(shù)據(jù)類型 不可以
弱類型語(yǔ)言 變量定義后是否可以隨意改變數(shù)據(jù)類型 可以
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蔑滓,隨后出現(xiàn)的幾起案子郊酒,更是在濱河造成了極大的恐慌,老刑警劉巖键袱,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件燎窘,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蹄咖,警方通過(guò)查閱死者的電腦和手機(jī)褐健,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)澜汤,“玉大人蚜迅,你說(shuō)我怎么就攤上這事舵匾。” “怎么了慢叨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵纽匙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我拍谐,道長(zhǎng)烛缔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任轩拨,我火速辦了婚禮践瓷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亡蓉。我一直安慰自己晕翠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布砍濒。 她就那樣靜靜地躺著淋肾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爸邢。 梳的紋絲不亂的頭發(fā)上樊卓,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音杠河,去河邊找鬼碌尔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛券敌,可吹牛的內(nèi)容都是我干的唾戚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼待诅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼叹坦!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起卑雁,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤立由,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后序厉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毕箍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年弛房,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片而柑。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡文捶,死狀恐怖荷逞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情粹排,我是刑警寧澤种远,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站顽耳,受9級(jí)特大地震影響坠敷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜射富,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一膝迎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧胰耗,春花似錦限次、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至赠群,卻和暖如春羊始,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乎串。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工店枣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叹誉。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓鸯两,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親长豁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钧唐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • TITLE: 編程語(yǔ)言亂燉 碼農(nóng)最大的煩惱——編程語(yǔ)言太多。不是我不學(xué)習(xí)匠襟,這世界變化快钝侠! 有時(shí)候還是蠻懷念十幾、二...
    碼園老農(nóng)閱讀 5,319評(píng)論 2 35
  • 天堂的名單里,沒(méi)有他的名字啃勉。他從未出生忽舟,從未死亡,從未存在。1900叮阅,海上鋼琴師刁品,一個(gè)傳奇中的傳奇。 《海上鋼琴師...
    渚清沙閱讀 905評(píng)論 3 5
  • 今天是我們芳老大親自講課浩姥,每一次聽(tīng)她講課感覺(jué)都是一種享受挑随!并且收獲頗多、每一次都是直切主題勒叠,讓我不禁恍然大悟兜挨!從現(xiàn)...
    FAB小太陽(yáng)閱讀 110評(píng)論 0 0
  • 親愛(ài)的Chloe: 見(jiàn)信如面暑劝,一切安好!不知深圳近幾日天氣如何颗搂?九月的湖南仍是驕陽(yáng)似火担猛,寫(xiě)信當(dāng)時(shí)窗外大風(fēng)起...
    大花是個(gè)好名字閱讀 376評(píng)論 0 0