小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Python 不是 Java

 xiao huan 2008-05-23

Python 不是 Java

Posted by ShiningRay on 3rd 四月 2006

作者:Phillip J. Eby.

翻譯:ShiningRay @ NirvanaStudio

原文地址:http:///2004/12/python-is-not-java.html


我最近正在看一個基于wxPython的GUI應用程序,大概45.5KLOC的樣子,但我沒有計算它用到的庫的大小(如Twisted)。代碼是 由那些對Python相對生疏的Java的開發(fā)者寫的,所以程序有很嚴重的性能問題(如三十秒的啟動時間)。我在檢查代碼的時候發(fā)現(xiàn)他們寫了很多對 Java有意義但是對Python卻很恐怖的東西。并不是因為“Python比Java慢”,而是因為在Python中有更方便的方法去完成同樣的目標, 甚至在Java中不可能的事情。

所以,可悲的事就是這些可憐人事倍功半,產(chǎn)生了很多很多不需要寫的代碼,從而比相應合乎Python習慣的寫法慢得多得多。我們來看一些例子:

  • 在Java中一個靜態(tài)的方法(static)不能翻譯成一個Python的類方法(classmethod)。哦,當然,多多少少他最終產(chǎn)生類似的 效果,但類方法的目的實際上是做了一些通常在Java中不可能的事(如繼承一個非默認的構造函數(shù))。Java靜態(tài)方法的習慣翻譯通常是一個模塊級函數(shù),而 不是一個類方法或靜態(tài)方法(staticmethod)。(同時靜態(tài)封閉(final)字段應該翻譯成模塊級常量。)

    這并不是一個性能上的問題,但是一個Python程序員要用像這些類似Java習慣的代碼的話,可能就會被在該輸入 Foo.someFunction時卻要輸入Foo.Foo.someMethod這種情況給惹毛了。但是請注意:調用一個類方法將會比調用一個靜態(tài)方法 和函數(shù)要多一部分額外的內(nèi)存。

    啊,那些Foo.Bar.Baz也不是省油的。在Java中,這些點分割的名稱是由編譯器去查找的,所以運行時根本無所謂你有多少點。在 Python中,每次運行時都要查找,所以每個點都要計算在內(nèi)。(Python中一定要記住這點,“平鋪比嵌套好”,盡管比起性能,他和“可讀性”和“簡 單就是美”更靠近。)

  • 要用switch語句?Python翻譯將是一個哈希表,不是一堆if-then語句。用一堆if-then在Java中也不是switch語 句,如果有字符串參與了呢?他其實是一個哈希表。CPython字典實現(xiàn)用了性能最佳—在我們宇宙中目前所知道的—的哈希表的實現(xiàn)之一。你自己所寫的代碼 也不會比這個再好了,除非你是Guido、Tim Peters和Raymond Hettinger的“私生子”——還是遺傳增強了的。
  • XML不是答案。它也不是一個問題。要在正則表達式上解釋Jamie Zawinski,“一些人,當遇到一個問題的時候,就想‘我知道,我要用XML’那這個時候,他們就有兩個問題了。”

    和Java比這個一個不同的情況,因為比起Java代碼,XML是輕巧而且有彈性的。但比起Python的代碼來,XML就是一個船錨,一個絆腳 石。在Python中,XML是用來做交換,而不是你的核心功能,因為你不需要這么做。在Java中,XML可能是你的大救星因為他讓你實現(xiàn)了特定領域的 語言并“不通過編碼”提高了你的應用程序的適應性。在Java中,避免編碼是一個很大的優(yōu)勢,因為編碼意味著重新編譯。但在Python中,更常見的是, 寫代碼比寫XML更方便簡單。同時Python處理代碼要遠遠比處理XML快。(不僅僅是這個,你必須書XML處理代碼,同時Python自身就已經(jīng)為你 準備好了。)

    如果你是一個Java程序員,對于你是否要在你的Python核心應用中使用XML作為一部分,不要相信你的本能。如果你不是因為信息交互的原因去 實現(xiàn)一個已經(jīng)存在的XML標準或是建立某種導入、導出格式或者建立某種XML編輯器或處理工具,那么就不要這么做。一次也別。甚至連想都不要想。現(xiàn)在,扔 掉那個XML模式把你的手解放吧!如果你的應用程序或者平臺要被Python開發(fā)者使用,他們只會感謝你不要在他們的工作量中添加使用XML的負擔。

    (這里唯一的例外是如果你的受眾的的確確,確確實實需要XML,出于某種奇怪的理由。像,他們拒絕學習Python并只對你使用了XML而付錢給 你,或者你打算給他們一個編輯XML的GUI,同時這個寫XML的GUI呢是另一個人寫的,同時你得到免費使用的權利。還有一些很少見的架構上的原因需要 用到XML。相信我,他們不會出現(xiàn)在你的程序中。如果有疑問,對一個資深的Python開發(fā)員解釋你的用例。或者,如果你臉皮厚的話,試試向一個Lisp 程序解釋你的程序為什么要用XML!)

  • Getter和setter是壞蛋。壞蛋,魔鬼!Python對象不是Java Bean。不要寫什么getter和setter,然后還把它們包裝在“屬性”里面。它直到你能證明你需要比一個簡單訪問復雜一點的功能時才有意義,否 則,不要寫getter和setter。它們是CPU時間的浪費,更要緊的是,它們還是程序員寶貴時間的極大浪費。不僅僅對于寫代碼和測試的人,對于那些 要閱讀和理解它們的人也是。

    在Java中,你必須使用getter和setter因為公共字段不允許你以后改變想法再去使用getter和setter。在Python中,這 樣做很傻,因為你可以以一個普通特性開始并可以在任何時間改變你的想法,而不用影響到這個類的任何客戶。所以不要寫getter和setter。

  • 代碼重復在Java中常常是一個不得不要的魔鬼,你必須經(jīng)常一遍一遍寫同一個方法而只有一點點的變化(通常是因為靜態(tài)類型約束)。在Python中 這樣做是沒有必要的也是不值得的(除了極少數(shù)一些特定的場合需要內(nèi)聯(lián)一些要求性能的函數(shù))。如果你發(fā)現(xiàn)自己一遍一遍在寫同樣的代碼而且變化很少,你就需要 去學一下閉包。他們并不是真的很可怕。

    這就是你要做的。你寫了一個包含了函數(shù)的函數(shù)。這里內(nèi)部的函數(shù)就是你要一遍遍寫的函數(shù)的模版,但是在里面加入了針對不同情況的函數(shù)要使用變量。外部 的函數(shù)需要剛剛提高的那種變量作為參數(shù),并且將內(nèi)部的函數(shù)作為結果返回。然后,每次你要寫另一種略微不同的函數(shù)的時候,你只要調用這個外部的函數(shù),并且把 返回值賦給你要讓“重復”函數(shù)出現(xiàn)的名字?,F(xiàn)在,如果你需要改變這個工作方式,你只要改變一個地方:這個模版。 

在我所看過的應用程序/平臺中,只有一個很微不足道的程序使用了這個技術之后可以去掉數(shù)百行重復代碼。事實上,自從開發(fā)者使用了特別的樣板文件來為這平臺開發(fā)插件,這會節(jié)省很多很多第三方開發(fā)人員的代碼,同時也使那些程序員要學習的東西簡化了。

這只是Java->Python思維方式轉變的冰山一角而已,現(xiàn)在我可以讓他轉變成正確的而不用鉆研這個程序的細節(jié)。本質上,如果你曾經(jīng)用過 一段時間Java,而且對Python比較陌生,不要太相信自己的本能。你的本能已經(jīng)為Java調節(jié),而不是Python。向后退一步,最重要的,不要寫 這么多代碼了。

要這樣做,讓自己覺得更加需要Python。假裝好像Python是可以做任何你想做的魔棒,卻讓你無須動一個手指。問一下,“Python是怎樣 解決我的問題的?”還有“Python語言的哪個特點和我的問題最相似?”你絕對會驚訝于你需要的東西其實已經(jīng)有了某種固定形式。事實上,這種現(xiàn)象實在是 太普遍了,甚至在很有經(jīng)驗的Python程序員中也會出現(xiàn),以至于Python社區(qū)中給這種現(xiàn)象起了個名字。我們稱之為“GUIDO的時間機器” (GUIDO是美語中太空飛行工程師的意思),因為有時候看上去得到我們所需要的東西好像只有他知道的一種方法,但當我們自己知道了就不一樣了。

所以,如果你不能感到你在使用Python時至少比用Java要多出10倍的生產(chǎn)力,?。ㄍ瑫r如果你還懷念你的Java IDE,考慮一下這種可能性:因為你寫的Python程序比他所需要的要復雜得多)


附錄:(翻譯自此篇文章的評論) 

確實,哈希表==字典。舉個最簡單的例子,從Python

標準庫中檢出“pickle”和“copy”模塊,這兩個模塊會從字典中查找類型并調用相應的函數(shù)。另一個有些詭異的例子是范型函數(shù),我已經(jīng)在最近的Blog中寫了一下。

關于閉包的例子,我這里給出一個很笨的例子。假設你要寫很多這樣的函數(shù): 

def addOne(x): return x+1
def addTwo(x): return x+2

然后你可以這樣寫:

def makeAdder(addend):
… def add_it(x): return x+addend
… return add_it

并且這樣使用: 

 

addOne = makeAdder(1)
addTwo = makeAdder(2)

這樣就可以等同于原來的定義了。 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多