设为首页 收藏本站
查看: 678|回复: 0

[经验分享] Python把C语言打得满地找牙

[复制链接]

尚未签到

发表于 2015-4-26 05:36:54 | 显示全部楼层 |阅读模式
  好吧,我承认我又标题党了,不该把Python拉出来和C比,我绝无轻视C语言的意思。我想说的只是,在解决某些问题是,比起用C,用Python真是太舒服了。
  《Beautiful Code》开篇第一章是由大神Brian Kernighan讲解另一位半神半程序员Rob Pike设计的C语言“正则”表达式引擎(“正则“二字打引号的原因下面会说明)。不能不说短短几十行代码是让人叹为观止的大师杰作。 具体好在哪里我也不重复了,如果我都能对这段代码头头是道,那也不劳Kernighan亲自出场赞不绝口了。总之,他说:I was amazed by how compact and elegant this code was... 我觉得,既然Kernighan都如此赞赏,论“compat and elegant”,这一定是C语言的最高境界了。估计这也是程序设计的最高境界了吧?一段时间里,我深信不疑,直到有一天,我看见了这个Regular expression engine in 14 lines of Python。再次惊叹。

  首先,整理一下这段代码,实际上,原帖中的代码还不够精简,因为它用3行实现了一个Python标准库中已有的函数。取消这三行,改为用import引入库函数,得到的代码如下:


from itertools import chain as iconcat
def nil(s): yield s
def seq(l, r):
    return lambda s: (sr for sl in l(s) for sr in r(sl))
def alt(l, r):
    return lambda s: iconcat(l(s), r(s))
def star(e):
    return lambda s: iconcat(nil(s), seq(e, star(e))(s))
def plus(e): return seq(e, star(e))
def char(c):
    def match(s):
        if s and s[0] == c: yield s[1:]
    return match
  就代码量来看,和《Beautiful Code》中的C“正则”引擎相差不大,但此Python实现的正则引擎在功能和简单性上都有无可比拟的优势,在分析这个正则引擎如何使用,顺带说明其工作原理后,再来看它的好处。

  使用这个正则引擎时首先用char, nil, sq, alt, star, plus这几个函数构造出一个正则表达式,用BNF记号表示,格式是这样的:

  exp -> char(c) |
       nil |
       seq(exp, exp) |              
       alt(exp, exp) |
       star(exp) |
       plus(exp)

  其语义为:
  exp->char(c) 表示匹配以字母c开头的字符串;

  exp->nil 表示匹配一个空字符串;

  exp->seq(exp1, exp2)表示如果exp1匹配s1,exp2匹配s2,则exp匹配由s1和s2连接成的字符串;

  exp->alt(exp1, exp2)表示字符串s必须匹配exp1或exp2中的一个;

  exp->star(exp1)匹配空字符串,或由一个或多个匹配exp1的子字符串连接成的字符串;

  exp->plus(exp1)匹配由一个或多个匹配exp1的子字符串连接成的字符串。

  总之不论格式还是语义它都和教科书上的正则表达式完全一致。例如,正则表达式e=c(a|d)*r用这个正则引擎表到出来就是:

  e = seq(char('c'),

  seq(plus(alt(char('a'), char('d'))),
  char('r'))
  现在是使用的问题了。构造出来的正则表达式的Python类型是函数,此函数接受一个参数,即被匹配的字符串。调用此函数得到的结果是一个集合,其中每一个元素为一个字符串,对应一个正则表达式和目标字符串的匹配,而这个字符串的内容就是目标字符串中剩下的无法匹配的部分。也就是说,如果正则表达式可以和目标字符串匹配,则返回的集合不为空,反之则得到一个空集合,因此,我们可以用:
  if e(str):
  来判断正则表达式e是否和字符串str匹配。

  要理解这个正则引擎的工作原理,只要抓住前述的一点“调用此函数得到的结果是一个集合,其中每一个元素为一个字符串,对应一个正则表达式和目标字符串的匹配,而这个字符串的内容就是目标字符串中剩下的无法匹配的部分“。实际上nil, char, seq, alt, plus中的每一个都符合此定义。这也是此Python正则引擎设计的好处之一:简单明了,易于理解,易于实现,易于确保正确。要写出《Beautiful Code》中的正则引擎是相当难的。我承认,以我的水平,即使Rob Pike把他的设计告诉我让我写代码,我也无法正确的写出。循环、指针还有边界条件,实在太容易出错了,这样的代码,非出自大师之手不可。而Python版的正则引擎就不一样,简单清晰的语义,很好的模块性,即使让我来写也可一次写对。

  虽然代码量相当,但是此Python 在功能上大大强过C版。首先,C版并不是一个真正的正则引擎。它无法表达“匹配exp1或匹配exp2”,这大大的限制它的实用性,而Python版是教科书式的标准正则引擎。其次,C版不能表达(abc)*这样的表达式,即其Kleene closure中的内容只能是一个字母,而Python版Kleene closure中可以是任何表达式。这就是为什么开头“正则”二字要加引号。

  此Python版代码的可组合性也比C版好。如果要在原有的基础上添加功能,Python版的用户只需要添加新的函数,而C版则要修改已有函数,难易程度不可同日耳语。比如注意到Python版没有“匹配任意字符”的功能,我们只需添加两行代码即可实现此功能:
  def any(s):
    yield s[1:]

  不仅实现简单,而且因为不改动已有代码,测试也容易。

  为什么在实现一个简单的正则引擎这个任务上,Python比C版顺手许多呢。看看Python版中用到的C所不具备的语言特性:generator function, generator expression, 高阶函数,string slicing。string slicing不仅仅是一个简单的产生子字符串的表达式,支撑其易用性是Python的自动内存管理。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-60604-1-1.html 上篇帖子: ArcGIS 9.2 笔记(5):Georocessing与Python 下篇帖子: boost.python的安装配置和初次使用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表