http://www.cda.cn/view/25735.html

通過實例淺析Python對比C語言的編程思想差異

我一直使用 Python,用它處理各種數據科學項目。 Python 以易用聞名。有編碼經驗者學習數天就能上手(或有效使用它)。
聽起來很不錯,不過,如果你既用 Python,同時也是用其他語言,比如說 C 的話,或許會存在一些問題。
給你舉個我自己經歷的例子吧。 我精通命令式語言,如 C 和 C 。對古老經典的語言如 Lisp 和 Prolog 能熟練使用。另外,我也用過 Java,Javascript 和 PHP 一段時間。(那么,學習) Python 對我來講不是很簡單嗎?事實上,只是看起來容易,我給自己挖了個坑:我像用 C 一樣去用 Python。
具體情況,請向下看。
一個最近的項目中,需要處理地理空間數據。給出(任務)是 gps 追蹤 25,000 個左右位置點,需要根據給定的經緯度,重復定位距離最短的點。我第一反應是,翻查(已經實現的)計算已知經緯度兩點間距離的代碼片段。代碼可以在 John D. Cook 寫的這篇 code available in the public domain 中找得到。
萬事俱備! 只要寫一段 Python 函數,返回與輸入坐標距離最短的點索引(25,000 點數組中的索引),就萬事大吉了:?? ?
def closest_distance(lat,lon,trkpts):
? d = 100000.0
? best = -1
? r = trkpts.index
? for i in r:
??? lati = trkpts.ix[i,'Lat']
??? loni = trkpts.ix[i,'Lon']
??? md = distance_on_unit_sphere(lat, lon, lati, loni)
??? if d > md
????? best = i
????? d = md
? return best
其中, distance_on_unit_sphere 是 John D. Cook's 書中的函數,trkpts 是數組,包含 gps 追蹤的點坐標(實際上,是 pandas 中的數據幀,注,pandas 是 python 第三方數據分析擴展包)。
上述函數與我以前用 C 實現的函數基本相同。 它遍歷(迭代)trkpts 數組,將迄今為止(距離給定坐標位置)的距離最短的點索引值,保存到本地變量 best 中。
目前為止,情況還不錯,雖然 Python 語法與 C 有很多差別,但寫這段代碼,并沒有花去我太多時間。
代碼寫起來快,但執行起來卻很慢。例如,我指定428 個點,命名為waypoints(導航點,路點,導航路線中的關鍵點)。導航時,我要為每個導航點 waypoint 找出距離最短的點。為 428 個導航點 waypoint 查找距離最短點的程序,在我的筆記本上運行了 3 分 6 秒。
之后,我改為查詢計算曼哈坦距離,這是近似值。我不再計算兩點間的精確距離,而是計算東西軸距離和南北軸距離。計算曼哈坦距離的函數如下:?? ?
def manhattan_distance(lat1, lon1, lat2, lon2):
? lat = (lat1 lat2)/2.0
? return abs(lat1-lat2) abs(math.cos(math.radians(lat))*(lon1-lon2))

實際上,我用了一個更簡化的函數,忽略一個因素,即維度曲線上 1 度差距比經度曲線上的 1 度差距要大得多。簡化函數如下:?? ?
def manhattan_distance1(lat1, lon1, lat2, lon2):
? return abs(lat1-lat2) abs(lon1-lon2)

closest 函數修改為:?? ?
def closest_manhattan_distance1(lat,lon,trkpts):
? d = 100000.0
? best = -1
? r = trkpts.index
? for i in r:
??? lati = trkpts.ix[i,'Lat']
??? loni = trkpts.ix[i,'Lon']
??? md = manhattan_distance1(lat, lon, lati, loni)
??? if d > md
????? best = i
????? d = md
? return best
如果將 Manhattan_distance 函數體換進來,速度還可以快些:?? ?
def closest_manhattan_distance2(lat,lon,trkpts):
? d = 100000.0
? best = -1
? r = trkpts.index
? for i in r:
??? lati = trkpts.ix[i,'Lat']
??? loni = trkpts.ix[i,'Lon']
??? md = abs(lat-lati) abs(lon-loni)
??? if d > md
????? best = i
????? d = md
? return best
在計算的最短距離點上,用這個函數與用 John's 的函數效果相同。我希望我的直覺是對的。越簡單就越快。現在這個程序用了 2 分 37 秒。提速了 18%。 很好,但還不夠激動人心。
我決定正確使用 Python。這意味著要利用 pandas 支持的數組運算。這些數組運算操作源于 numpy 包。通過調用這些數組操作,代碼實現更簡練:?? ?
def closest(lat,lon,trkpts):
? cl = numpy.abs(trkpts.Lat - lat) numpy.abs(trkpts.Lon - lon)
? return cl.idxmin()
該函數與之前函數的返回結果相同。在我的筆記本上運行時間花費了 0.5 秒。整整快了 300 倍! 300 倍,,也即30,000 %。不可思議。 提速的原因是 numpy 數組操作運算用 C 實現。因此, 我們將最好的兩面結合起來了: 我們得到 C 的速度和 Python 的簡潔性。
教訓很明確:別用 C 的方式寫 Python 代碼。用 numpy 數組運算,不要用數組遍歷。對我來說,這是思維上的轉變。
Update on July 2, 2015。文章討論在Hacker News。一些評論沒有注意到(missed )我用到了 pandas 數據幀的情況。主要是它在數據分析中很常用。如果我只是要快速的查詢最短距離點,且我時間充分,我可以使用 C 或 C 編寫四叉樹(實現)。
Second update on July 2, 2015。有個評論提到 numba 也能對代碼提速。我就試了一下。
這是我的做法,與你的情況不一定相同。 首先,要說明的是,不同的 python 安裝版,實驗的結果不一定相同。我的實驗環境是 windows 系統上安裝 Anaconda,同時也安裝了一些擴展包。可能這些包和 numba 存在干擾。.
首先,輸入下面的安裝命令,安裝 numba:?? ?
$ conda install numba

這是我命令行界面上的反饋:

之后我發現,numba 在 anaconda 安裝套件中已存在。 也可能安裝指令有變更也說不定。
推薦的 numba 用法:?? ?
@jit
def closest_func(lat,lon,trkpts,func):
? d = 100000.0
? best = -1
? r = trkpts.index
? for i in r:
??? lati = trkpts.ix[i,'Lat']
??? loni = trkpts.ix[i,'Lon']
??? md = abs(lat - lati) abs(lon - loni)
??? if d > md:
????? #print d, dlat, dlon, lati, loni
????? best = i
????? d = md
? return best

我沒有發現運行時間提高。我也嘗試了更積極的編譯參數設置:?? ?
@jit(nopython=True)
def closest_func(lat,lon,trkpts,func):
? d = 100000.0
? best = -1
? r = trkpts.index
? for i in r:
??? lati = trkpts.ix[i,'Lat']
??? loni = trkpts.ix[i,'Lon']
??? md = abs(lat - lati) abs(lon - loni)
??? if d > md:
????? #print d, dlat, dlon, lati, loni
????? best = i
????? d = md
? return best
這次運行代碼時,出現一個錯誤:

看來,pandas 比 numba 處理代碼更智能。
當然,我也能花時間修改數據結構,使 numba 能正確編譯(compile)。可是,我為什么要這么干呢? 用 numpy 寫的代碼運行的足夠快了。反正,我一直在用 numpy 和 pandas 。為什么不繼續用呢?
也有建議我用pypy。這當然有意義,不過…我用的是托管服務器上的 Jupyter notebooks(注,在線瀏覽器的 python 交互式開發環境)。我用的是它提供的 python 內核,也即,官方的(regular)Python 2.7.x 內核。并沒有提供 Pypy 選擇。
也有建議用 Cython。好吧,如果我回頭要編譯代碼 ,那我干脆直接用 C 和 C 就好了。我用 python,是因為,它提供了基于 notebooks(注:網頁版在線開發環境)的交互式特性,可以快速原型實現。這卻不是 Cython 的設計目標。

?

轉載于:https://www.cnblogs.com/amengduo/p/9586322.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/251360.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/251360.shtml
英文地址,請注明出處:http://en.pswp.cn/news/251360.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端知識點梳理(一)

一、HTML 1. meta標簽 記住2個屬性&#xff1a;name和http-equiv name&#xff1a;描述網頁 <meta name"參數" content"具體的描述">http-equiv&#xff1a;文件頭 HTML中的meta標簽及其使用方法 二、CSS 1. css實現水平居中的幾種方式 css實…

Babel 7 基礎入門學習(詳細版)

可以在我的GitHub上下載示例代碼。 前言 之前一直想要系統的學習一下Babel的使用規則&#xff0c;看過阮一峰老師的《Babel基礎入門》&#xff0c;無奈此教程是2016年出的&#xff0c;而Babel 7都已經出來啦&#xff0c;于是&#xff0c;在搜集了各種資料后&#xff0c;關于…

JS的DOM操作

1.DOM節點 &#xff08;1&#xff09;node.offsetParent最近的有定位屬性的祖先節點 如果祖先節點都沒有定位&#xff0c;那么默認為body &#xff08;2&#xff09;node.offsetLeft/node.offsetTop 距離最近的有定位屬性的祖先節點的距離 node.offsetLeft左外邊框到定位父級的…

Kubernetes學習之路(四)之Node節點二進制部署

K8S Node節點部署 1、部署kubelet &#xff08;1&#xff09;二進制包準備 [rootlinux-node1 ~]# cd /usr/local/src/kubernetes/server/bin/ [rootlinux-node1 bin]# cp kubelet kube-proxy /opt/kubernetes/bin/ [rootlinux-node1 bin]# scp kubelet kube-proxy 192.168.56.1…

前端知識點梳理(二)

1.內核 瀏覽器內核&#xff08;Rendering Engine&#xff09;最初分為&#xff1a;渲染引擎&#xff08;layout engineer&#xff09;或&#xff08;Rendering Engine&#xff09;和js引擎&#xff1b;后來 JS 引擎越來越獨立&#xff0c;內核就傾向于單指渲染引擎。瀏覽器she…

微信小程序模仿開眼視頻app(三)——信息卡片瀑布流和分類

《微信小程序模仿開眼視頻app&#xff08;一&#xff09;——視頻首頁、視頻詳情、分類》 《微信小程序模仿開眼視頻app&#xff08;二&#xff09;——搜索功能》 可到我的github賬號上去copy文件 瀑布流部分 文件代碼提示的挺詳細的&#xff0c;這里主要點一下 社區與分類…

PHP后臺代碼解決跨域問題

在前端里面&#xff0c;解決跨域的時候總顯得那么的惡心&#xff0c;什么jsonp啊&#xff0c;ajax啊&#xff0c;CORS啊什么的&#xff0c;總覺得是在鉆空子進行跨域&#xff0c;其實在PHP文件里面只需要加一段代碼就可以跨域了&#xff0c;前端你該怎么寫還是怎么寫&#xff0…

javascript --- typeof方法和instanceof方法

ES5中: 原始類型包括:Number、String、Boolean、Null、Undefined 原始封裝類型包括:Number、String、Boolean 引用類型包括:Array、Function、RegExp、Error、Date、Error 變量對象 原始類型的實例成為原始值,它直接保存在變量對象中. 引用類型的實例成為引用值,它作為一個指針…

python 基本數據類型常用方法總結

【引言】 python中基本數據類型的有很多常用方法&#xff0c;熟悉這些方法有助于不僅提升了編碼效率&#xff0c;而且能寫出高質量代碼&#xff0c;本文做總結 int .bit_length:返回二進制長度 str 切片索引超出不會報錯 切片上下限寫反不報錯&#xff0c;沒有結果 切片倒取&am…

網易試題——關于箭頭函數與this和arguments的關系

昨天做試題的時候遇到了這個題目 var a 1;function fn1() {console.log(this.a)}const fn2 () > {console.log(this.a)}const obj {a: 10,fn1: fn1,fn2: fn2}fn1()fn2()obj.fn1()obj.fn2() 哦這該死的網易&#xff0c;怎么出這么簡單的題目&#xff0c;答案是&#xff1…

《JavaScript 高級程序設計》筆記 第1~5章

第1章 js是專為網頁交互而設計的腳本語言&#xff0c;由3部分組成&#xff1a; ECMAScript&#xff0c;提供核心語言功能DOM文檔對象模型&#xff0c;提供訪問和操作網頁內容的方法和接口BOM瀏覽器對象模型&#xff0c;提供與瀏覽器交互的方法和接口 js是一種腳本語言、解釋…

【筆記】跨域重定向中使用Ajax(XHR請求)導致跨域失敗

背景&#xff1a; 1、前端Web中有兩個域名&#xff0c;a.com和b.com&#xff0c;其中a.com是訪問主站&#xff08;頁面&#xff09;&#xff0c;b.com是數據提交接口的服務器&#xff08;XHR請求&#xff09; 2、a.com中用XHR調用b.com/cerate【沒有指定協議】&#xff0c;保存…

javascript --- js中prototype、__proto__、[[Propto]]、constructor的關系

首先看下面一行代碼: function Person(name){this.name name; } var person1 new Person; console.log(person1.__proto__ Person.prototype); console.log(person1.constructor Person);控制臺打印如下: 可以看見,當使用構造函數(Person)構造一個實例(person1)時, 在后…

前端知識點整理收集(不定時更新~)

知識點都是搜集各種大佬們的&#xff0c;如有冒犯&#xff0c;請告知&#xff01; 目錄 原型鏈 New關鍵字的執行過程 ES6——class constructor方法 類的實例對象 不存在變量提升 super 關鍵字 ES6——...&#xff08;展開/收集&#xff09;運算符 面向對象的理解 關…

數據庫四大特性與隔離級別

數據庫四大特性ACID Atomicity (原子性) :事務&#xff08;transaction&#xff09;是由指邏輯上對數據的的一組操作&#xff0c;這組操作要么一次全部成功&#xff0c;如果這組操作全部失敗&#xff0c;是不可分割的一個工作單位。 Consistency(一致性) :在事務開始以前&#…

重學《JavaScript 高級程序設計》筆記 第6章對象

第6章 面向對象的程序設計 ECMAScript中沒有類的概念&#xff1b; 1.創建對象-歷史 1.1 創建實例&#xff0c;添加方法和屬性 → 對象字面量 缺點&#xff1a; 使用同一接口創建很多對象&#xff0c;產生大量重復代碼 var person new Object() person.name "Y" pe…

Java-reflect(反射)初步理解_1

27.01_反射(類的加載概述和加載時機) A:類的加載概述 當程序要使用某個類時&#xff0c;如果該類還未被加載到內存中&#xff0c;則系統會通過加載&#xff0c;連接&#xff0c;初始化三步來實現對這個類進行初始化。加載 就是指將class文件讀入內存&#xff0c;并為之創建一個…

javascrip --- 構造函數的繼承

兩點需要注意的. 第一是在構造函數聲明時,會同時創建一個該構造函數的原型對象,而該原型對象是繼承自Object的原型對象 // 聲明一個構造函數Rectengle function Rectangle(length, width) {this.length length;this.width width; }// 即:看見function 后面函數名是大寫,一般…

Ruby實例方法和類方法的簡寫

創建: 2017/12/12 類方法 Sample.func實例方法 Sample#func轉載于:https://www.cnblogs.com/lancgg/p/8281677.html

《JavaScript 高級程序設計》筆記 第7章及以后

第7章 函數表達式 匿名函數的name屬性是空字符串&#xff1b;閉包是函數&#xff1a;閉包是有權訪問另一個函數作用域中變量的函數&#xff1b;(P181 副作用,解釋了點擊li彈出循環最后值的原因)當某個函數第一次被調用時&#xff0c;會創建一個執行環境及相應作用域鏈&#xf…