Java帝國對Python的滲透能成功嗎?
作者 | 劉欣
轉載自碼農翻身(公眾號 ID:coderising)
引子
Java 帝國已經成立 20 多年,經過歷代國王的勵精圖治,可以說是地大物博,碼農眾多。
可是國王依然不滿足,整天想著如何繼續開拓疆土, 這一天晚上他又把幾個重臣招來商議了。
IO大臣說:“陛下,現在天下大勢初定,我 Java 帝國已經佔據了後端開發,大資料,Android 開發等重要地盤,再想擴充殊為不易!”
“是啊, 前端被 JavaScript 所盤踞,我們很難滲透啊。” 執行緒大臣補充。
國王點點頭,這話不錯,JavaScript 一統前端,Flash 消失了,Applet 不見了。想到 Applet,國王就一陣心痛,當時 Java 是靠了 Applet 才引起碼農的關注,一炮走紅,後來怎麼就不行了呢?
“那人工智慧呢?” 國王狠狠地問道。
“陛下明鑑,人工智慧底層都是 C/C++ 的地盤,應用層被 Python 等所侵佔。 ” JDBC大臣回答。
“雲端計算呢?”
“似乎是 Go 語言的地盤。”
“嘶——” 國王覺得有點牙疼。
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 王國的吉森, 他怎麼一點訊息都沒有呢? 是時候再派一個人去了......
(本文為 AI科技大本營轉載文章,轉載請聯絡原作者)
◆
徵稿
◆
推薦閱讀:
❤點選“閱讀原文”,檢視歷史精彩文章。
相關文章
- 看看國外的 JS 題,你能全部做對嗎?JS
- 不懂程式,能看明白「黑客帝國」嗎?黑客
- 不懂程式,能看明白《黑客帝國》嗎?黑客
- 滲透測試某大型能源公司續(成功滲透區域網閘道器防火牆)防火牆
- 什麼是滲透測試?網站有必要進行滲透測試嗎?網站
- 小米要做智慧電飯煲和腳踏車:雷軍的帝國夢能實現嗎?
- 第六章-實用滲透技巧-1:針對雲環境的滲透
- 對於Spring Boot的滲透姿勢Spring Boot
- 內網滲透-初探域滲透內網
- 針對網路服務的滲透測試
- wifi滲透WiFi
- 帝國cms生成的地址可以改嗎怎麼改回來
- 內網滲透應用 跨vlan滲透的一種思路內網
- 域滲透之利用WMI來橫向滲透
- python滲透測試入門——Scapy庫Python
- 帝國cms登陸成功後又馬上退出的解決辦法
- metasploit滲透測試筆記(內網滲透篇)筆記內網
- 滲透測試會用到哪些工具?滲透測試教程
- Kali Linux 安全滲透教程1.2 安全滲透所需工具Linux
- WaterO反滲透式智慧淨水器:還能提醒你喝水
- 馬斯克的商業帝國馬斯克
- 網路安全滲透測試的型別!滲透測試入門教程型別
- 10款最好用的滲透測試工具,你還不知道嗎?
- Java可以自學嗎?自學能學好嗎?Java
- Me-and-My-Girlfriend-1靶機滲透 (Vulnhub內網滲透)內網
- 滲透測試好學嗎?都需要學習哪些技術?
- 後“帝國”時代:微軟在《帝國時代2》之後的RTS嘗試微軟
- 域滲透——Hook PasswordChangeNotifyHook
- pentestdb滲透工具使用
- 伺服器滲透?伺服器
- 網站滲透思路網站
- 內網滲透工具內網
- python滲透測試入門——流量嗅探器Python
- 【原創】記一次對X呼APP的滲透測試APP
- python能開發前端嗎Python前端
- 滲透測試對檔案包含漏洞網站檢測網站
- NoSQL:一個帝國的崛起SQL
- 《財富的帝國》筆記筆記