Java 帝國已經成立20多年,通過歷代國王的勵精圖治,能夠說是地大物博,碼農衆多。 前端
但是國王依然不知足,成天想着如何繼續開拓疆土, 這一天晚上他又把幾個重臣招來商議了。 數據庫
IO大臣說:「陛下,如今天下大勢初定,我Java帝國已經佔據了後端開發,大數據,Android開發等重要地盤,再想拓展殊爲不易!」 後端
「是啊, 前端被JavaScript所盤踞,咱們很難滲透啊。」 線程大臣補充。 網絡
國王點點頭,這話不錯,JavaScript一統前端,Flash消失了,Applet不見了。想到Applet,國王就一陣心痛,當時Java是靠了Applet才引發碼農的關注,一炮走紅,後來怎麼就不行了呢?測試
「那人工智能呢?」 國王狠狠地問道。 大數據
「陛下明鑑,人工智能底層都是C/C++的地盤,應用層被Python等所侵佔。 」 JDBC大臣回答。 this
「雲計算呢?」 雲計算
「彷佛是Go語言的地盤。」 人工智能
「嘶——」 國王以爲有點牙疼。 url
IO大臣趕忙爲君主分憂:「陛下,如今羣雄涿鹿,八分天下,邊境戰火連年不息,陛下不只維持住祖宗的基業,還有不小的擴展,已是一代聖主了,不過多年征戰,民力維艱,老臣有一計,也許能換來奇效。」
「愛卿快講!」
「老臣覺得不戰而屈人之兵纔是上策,做爲世界最強之王國,不只要武力上震懾羣雄,更要輸出我堂堂Java帝國之文化和價值觀。」
「什麼文化和價值觀?」
「首先咱們要大肆宣揚靜態語言的種種好處,好比編譯期檢查發現錯誤,代碼適合閱讀和維護,適合大規模團隊合做,口號我都想好了,就叫‘動態一時爽,重構火葬場!’ 」
「嗯,這口號不錯!」 國王讚許,「愛卿真是老成謀國。」
「但是有些語言也是靜態的啊!你怎麼宣傳?」 老對頭線程大臣發難。
「陛下您想一想,咱們有不少寶貝,」 IO大臣根本不理線程大臣, 繼續侃侃而談:「 好比IoC、AOP、反射、動態代理、泛型、註解、JDBC、JMS......還有咱們引覺得豪的JVM。這些東西,那些國家可不必定有,咱們派出老師,把這些東西灌輸給他們的臣民,讓他們體會到Java的種種好處,慢慢地就把他們給同化了!到時候他們的碼農天然而然就會加入我Java帝國。」
「陛下萬萬不可,不一樣的語言有不一樣的特色,咱們的文化別人是接受不了的,到時候只會引發羣雄恥笑。」 線程大臣以爲IO大臣腦洞大開,簡直是胡鬧,非要誤國不可。
「能夠一試嘛!」 國王牙不疼了,「此事由IO大臣全權負責,一年後看效果。」
做爲被派往Python王國的老師,吉森帶着IO大臣的重託,風塵僕僕,終於來到了Python 王國。
IO大臣在挑選人選的時候,有個重要的原則:是Java的死忠粉絲,最好是對其餘語言根本不瞭解,免得思想被污染。 這吉森就是其中的佼佼者。
吉森先找到一個地方安頓下來,而後邊四處閒逛, 他驚奇地發現,這裏類方法中的self滿天飛, 還有強制代碼縮進,果真和我大Java不一樣,很有異域風情。
前面是個茶館,人聲鼎沸, 吉森走了進去,看看能不能牛刀小試,宣揚一下Java的文化。
「小二,我觀察了半天,大家這裏怎麼沒有討論泛型啊?」 吉森拉住上茶的店小二。
「泛型? 那是什麼東西? 」 小二大惑不解。
「你確定是個外鄉人,不是來自C++就是Java,我說得沒錯吧?」 旁邊不知道何時來了一個老頭兒。
「老先生眼光不錯,我確實從Java王國來,我很納悶,這裏怎麼沒有泛型啊,據我所知,泛型能夠在編譯期作類型檢查,碼農們在寫代碼的時候也不須要作類型的轉換,很是好用的啊。」 吉森開始灌輸Java的種種好處。
List<String> files = new ArrayList<String>(); String file = files.get(0); //沒必要作強制類型轉換 files.add(new File(.....)) ; // 編譯錯誤
「外鄉人,咱們Python中的變量是不須要聲明類型的,不會作編譯期類型檢查,只有在運行時纔會檢查這個變量究竟是什麼類型,可否調用它的方法,你說,咱們要泛型有什麼用?」
吉森大驚,臥槽,這IO大臣怎麼沒告訴本身啊, 人家根本就沒這個需求!
想一想我大Java費了那麼大勁兒去實現泛型,沒想到在Python這裏徹底無用武之地, 還輸出什麼文化! 傳什麼教!
吉森以爲有點被IO大臣坑了! 不過多年的歷練只是讓他稍微慌亂,他立刻穩住神,轉移話題: 「先生所言極是,晚生還有一個問題,這Python能支持反射嗎? 」
在Java王國,人們常常經過反射的方式來獲取一個類的屬性、方法,而後根據一個字符串的名稱來調用某個類的方法。
好比有個url : /user?action=Login
系統根據約定解析它,肯定類是User, 方法是Login。而後就能夠把User對象建立起來,經過反射調用Login 方法。
public class User{ public void login(...){ ...... } }
「哈哈哈,你這個外鄉人啊,你知道爲何咱們Python是動態語言嗎? 咱們Python的反射功能不知道比大家Java強到哪裏去了!來來來,我給你看個例子。」
class User: def login(self): print("this is login")
「如今我打印他全部的方法:」
methods = [x for x, y in User.__dict__.items() if type(y) == FunctionType] print(methods) #輸出 ['login']
「接下來我經過反射調用Login方法, 老夫好久沒寫代碼了,可能不太嚴謹,你明白意思就行。」
url = "/user?action=login" #從url解析獲得類和action,代碼略 clz = "User" action = "login" #根據名稱得到User對象和方法 user = globals()[clz]() func = getattr(user,action) #獲取login方法 func() #輸出This is login
吉森看到這麼寥寥幾行代碼,就實現了基本的反射, 真是靈活啊,這Python真是不錯,他都有點羨慕了。
不, 我肩負IO大臣的重託, 我是來傳教的,不能讓這老頭兒給洗腦了!
吉森想起來了一個大殺器:動態代理,這但是Java的一個很是基礎的技術,能夠在運行時實現類和方法的加強,好比在調用業務方法的先後加上事務管理,日誌管理等功能,沒有動態代理,AOP就別想了。
吉森說道:「老先生,Python怎麼去實現動態代理啊?」
老頭兒微微一笑:「Java Class有個缺點, 一旦被裝入Java虛擬機,就無法修改了,想對他作加強,只能修改字節碼建立新的類,對老的類作封裝,就是代理。可是Python是個動態語言,在運行時就能夠修改啊,好比我能夠動態地給User類增長一個新的屬性,這一點你的Java作不到吧?」
setattr(User,"name",'andy') print(user.name) #andy
吉森看得目瞪口呆,這真是顛覆了本身從小養成的世界觀:一個類在運行期是不能改變的,更不可能去增長什麼屬性。
老頭兒又接着說:「你看看這個User類,和Proxy類,每次調用Login方法的時候,我均可以動態地建立一個新的方法出來,在這個新的方法中,就能夠作各類手腳了。」
class User: def login(self): print('user login') def logout(self): print('user logout') class Proxy: def __init__(self, target): self.target = target def __getattribute__(self, name): target = object.__getattribute__(self, "target") attr = object.__getattribute__(target, name) if name == 'login' : def newFunc(*args, **kwargs): print ("login start") result = attr(*args, **kwargs) print( "login end") return result return newFunc else : return attr u = User() p = Proxy(u) p.login() #實際上調用的是動態建立的方法 p.logout() #調用的是原來的方法
「你那個Proxy中的__getattribute__是什麼東西啊? 」 吉森看到魔法都在這裏,不禁得發問。
「每當你去調用一個方法(如login/logout),或者訪問一個字段的時候,Python都會經過__getattribute__先找到這個方法或者字段,而後纔是真正的調用。」
「奧,原來如此,你經過__getattribute__作了手腳,若是名稱是Login,就建立新的方法,在新的方法中除了調用老方法以外,還輸出了日誌。」
「不錯,孺子可教!」
吉森如今是真心佩服動態語言了,在Java中必須得在運行時經過操縱字節碼來加強,字節碼啊,那可不是通常人能玩的。這Python竟然在源碼級別就把功能給加強了!
吉森有點懷疑本身這次Python王國之行的效果了,這可如何是好? 怎麼回去向IO大臣覆命? 當初但是立下軍令狀的!
他忽然想起臨行前,IO大臣曾經送給本身三個錦囊,囑咐本身只有到了最危急的時刻才能打開,如今不開,更待什麼時候?
往懷中一摸,就發現錦囊只剩下了兩個,丟了一個,這回去估計要殺頭, 管不了那麼多了, 吉森迅速掏出一個,只見上面寫着一段話:GIL(全局解釋鎖),GIL是Python的命門,這把超級大鎖只容許一個線程得到Python解釋器的控制權, 簡單來講,同一時刻,只有一個線程能運行!
沒想到老頭兒淡淡一笑:「Python確實有GIL,但是這程序的瓶頸啊,它不在CPU, 而在於IO,就是用戶的輸入,數據庫的查許,網絡的訪問,線程等到有IO操做的時候,放棄GIL這個超級大鎖,讓別的線程去執行就是了。再說了,你真想利用多核的時候能夠用多個進程啊!」
第一個錦囊妙計被輕鬆化解, 吉森趕忙掏出第二個,上面幾個字:「動態一時爽,重構火葬場。」
「哈哈哈,」老頭兒狡黠地笑了起來:「這都是不瞭解狀況的外人的誤解,據說過Quora沒有?奧,上不了是吧!這Quora就是Python寫的,人家那測試用例寫得很是充分,重構也不怕! 因此啊關鍵是測試用例!」
第二個妙計又被化解, 吉森完全沒轍了。
看到吉森的神色變化,老頭兒開始代表身份:「實不相瞞,老夫乃是Python國王的特使,咱們的探子早就據說大家Java那什麼破老師計劃了,你一進入我國,就被盯上了,國王特意派我來,看看能不能說服你,留在我國。」
吉森想一想,回去也沒法交差,這Python彷佛還不錯,進退兩難之際,不妨先妥協,以圖未來,因而點點頭答應了。
一年之後, IO大臣開始盤點老師計劃,發現回來覆命的寥寥無幾,尤爲是去Python王國的吉森, 他怎麼一點消息都沒有呢? 是時候再派一我的去了......