京公网安备 11010802034615号
经营许可证编号:京B2-20210330
通过实例浅析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 的设计目标。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
初中毕业想考证,先确认“我能不能报”,再比较证书价值。学历门槛不够的证书,宣传再多也与你无关;能报但对应不上岗位的证书, ...
2026-11-02市场岗确有一批报考不设专业限制的证书,但“不限专业”只解决能不能报,真正决定值不值的是三件事:对应市场岗哪条子路径、招聘 ...
2026-11-02“大学生必考证书有哪些”这个问题,本身就藏着一个需要先拆掉的假设:似乎存在一份人人适用的必考清单。实际上,除了少数与毕业 ...
2026-11-02“最好考的一级证书”这个问题,最容易踩的坑不是选错证书,而是没先弄清“一级”在目标证书体系里到底指什么。有的体系里,一级 ...
2026-11-02“职业证书哪个含金量高”这个问题,很难用一张榜单回答。原因不复杂:证书的“含金量”取决于你拿它做什么。想进入必须持证的行 ...
2026-11-02“证件含金量排名”是搜索量很高的词,但直接给你一份“十大证书排行榜”的文章,基本可以跳过。原因很简单:证书的含金量不是单 ...
2026-11-02在校大专生能考的证书,大体分三类:通用能力类(英语等级、计算机等级、普通话水平测试)、职业技能等级类,以及部分不要求工作 ...
2026-11-02在家闲着想考个证书,最容易踩的坑是先去搜“含金量排行榜”,然后被一堆培训广告牵着走。更稳妥的顺序是反过来的:先看自己属于 ...
2026-11-02“注册类证书”不是一个可以随手列全的清单,它更像一个制度口径:通常指国家职业资格目录中设有注册管理、与执业准入挂钩的资格 ...
2026-11-02“现在考什么证有用”很难有统一答案。同一张证书,对想进会计事务所的人有用,对想做新媒体运营的人可能帮助有限;对需要评职称 ...
2026-11-02“适合女生考的证书有哪些含金量高”,这个问题里藏着两个容易走偏的前提。一是把“女生”当成职业属性,仿佛有一份统一的女性证 ...
2026-11-02先说结论:工商管理专业女生不必追“女生必考”榜单。证书有没有用,取决于它能不能对上你准备投的岗位。比较稳妥的做法,是先在 ...
2026-11-02“什么证好考又实用”这个问题,最怕两种回答:一种是列一堆“通过率高”的证书,却不告诉你考完能干什么;另一种是反过来只谈含 ...
2026-11-02“女士可以考哪些证书”并没有一份统一答案。真正决定你能考什么的,不是性别,而是三件事:你现在的身份(在校、在职还是准备转 ...
2026-11-02大专学历想考运营岗位证书,先给结论:能报的证书不少,但值得考的集中在三类——平台官方运营/投放认证、职业技能等级评价、数 ...
2026-11-02大学生判断一张证书是否重要,不用先看宣传热度,而要看四件事:它是否匹配你的目标岗位,校招时是否真用得上,在校期间是否具备 ...
2026-11-02先把结论说清楚:在校期间以2—4张核心证书为宜,其中1—2张通用底证、1—2张与目标岗位对应的方向证;高壁垒资格证只在符合报考 ...
2026-11-02大学生问证书推荐,最容易掉进的坑是“别人考什么我也考什么”。证书本身没有统一的含金量排序,同一张证,对目标岗位是硬门槛, ...
2026-11-02经管毕业生没有一张“通吃”的证书。比较有用的选择,是先按财会、金融、市场、人力、综合管理几个方向锁定目标岗位,再把证书分 ...
2026-11-02“程序员考什么证书含金量高”,没有放之四海皆准的答案。同样是“高含金量”,对后端开发、云原生工程师、数据开发和安全工程师 ...
2026-11-02