[技术] 谈谈Python

昨天的文章收获了不少有价值的回复。不少人发现了一个大bug,那就是「上帝的归上帝,撒旦的归撒旦」。囧死我了。脑手不同步这病怎么治啊~以后我写完文章争取好好复查一遍。

有个名叫「舟」的读者写了段很棒的评论,不敢独专,和大家分享:

几点看法,随便谈谈:1.应该是“上帝的归上帝,凯撒的归凯撒”,原意讲的是宗教和世俗的关系,很深刻,变成“撒旦的归撒旦”以后这句话的意思其实就很让人费解了… 2. IoC的确是个很好的东西,但我认为它和libc中那种供应用层调用的函数之间并不是一种简单的进化关系,二者是互补的缺一不可,从两个不同方向减少软件的重复。libc中其实也有IoC的东西,例如qsort。libc毕竟是一个底层库提供的是应用和系统的接口,所以不需要太多IoC的东西。不过IoC确实比那种简单供应用调用的函数更深奥一点,新手更不容易掌握一点,所以更值得拿出来说。3. 不觉得AOP与OOP/FP是一个量级的东西,AOP在OOP中完全可以通过Decorator模式解决,在FP中就更直接了当了,python中函数的decorator就是一种典型的高阶函数,是FP的东西。 今天讨论的这些东西其实都是一言难尽的,随便一段单独拿出来都够程序君写一整篇文章的了,哈哈

这个周末要给人培训python,所以干脆今天先讲讲python,作为预演。我之前的文章也在不同的场合都建议初学者学习python。原因在于python良好的文化,和丰富的应用场景。当然,很多我接触过的语言都很好,学起来也很有滋味,但是。。。谁让有句俗语说:「真正的程序员用C,聪明的程序员用python」呢。

(今天的文字最好还是横过来看)

文化和关怀

请打开任何一个python解释器,在里面输入:import this。我所了解的任何一门其他语言都没有如此巧妙而又大张旗鼓地将其文化写入了语言本身。

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

这段文字值得好好消化。你一定会好奇,this究竟是什么?如果你对python的package机制有了解,那么,你就应该知道该从python的安装路径下找这个源码this.py,打开一看,一段格式熟悉,但乱七八糟的文字,然后是一段代码:

d = {}
for c in (65, 97):
    for i in range(26):
        d[chr(i+c)] = chr((i+13) % 26 + c)

print "".join([d.get(c, c) for c in s])

看到这里,你会会心一笑,这就是程序员的无聊和可爱之处,也是一种隐藏在geek范(作者是在向凯撒密码致敬么?)下的人文关怀。

我喜欢python除了喜欢代码的写法,另外一个原因是喜欢读python的代码。其实我们工作的大部分时间在读别人的代码。读python代码总是比读其它代码舒服些。除了格式统一外(很高兴go也在这方面通过gofmt做了努力),python的文化某种程度上保证了其代码的可读性。

python的人文关怀还体现在无处不在的dirhelp上。在python shell(建议安装ipython)里,只要有了这两个武器,再加上一些必要的练习,你就能很快掌握一个新的库。还有什么比对初学者友好更友好的事情呢?

应用场景

python可以应用在很多场合:

  • 小工具,小脚本
  • 文本处理
  • 图形处理
  • 爬虫
  • 服务器
  • 网站
  • 数值运算
  • 构造原型
  • ...

基本上这些领域都有很棒的python库供你驱使。

语言能力

python的语言能力中规中矩,表现力稍弱于ruby。但它还是涵盖了从面向对象,函数式编程(有限支持)到元编程(有限支持)的主流思想和方法。由于昨天的文章中已经有几个python的例子来说明这一点,这里就不再重复。作为一个成功的语言,python并未固步自封,它一直在进行有益的进化。比如说2.5新加的with关键字,简化了try..finally结构,让代码更简洁漂亮(这一直是Python努力的方向):

with open('hello.txt') as f:
    f.write('Hello world!\n')

这等价于之前的写法:

f = open('hello.txt')
try:
    f.write('Hello world!\n')
finally:
    f.close()

更关键的是,只需实现几个magic function,这种语言能力便能为你所用:

class MyOpen:
    def __init__(self, filename, mode = 'r'):
        self.filename = filename
        self.mode = mode
    def __enter__(self):
        self.f = open(self.filename, self.mode)
        return self.f
    def __exit__(self, **unused):
        self.f.close()

with MyOpen('hello.txt') as f:
    f.write('hello world!\n')

有意思的库和工具

现代编程语言的竞争是语言能力的竞争,也是语言的库和工具的竞争。对python而言,标准库为你提供了各种基本的能力,社区里繁多的第三方库更是将这种能力推到了一个新的高度。比如说github上著名的"kennethreitz/requests"库,它让http client的撰写简直就像写文章一样简单直观:

In [5]: import requests

In [6]: r = requests.get('https://api.github.com', auth=('user', 'pass'))

In [7]: r.status_code
Out[7]: 200

In [9]: r.json()
Out[9]:
{...}

In [10]: r.text
Out[10]: u'{"..."}'

利用这样的类库,加上github api,你可以十几二十行代码就撰写一个代码全文搜索工具。这就是web时代的生产力。

再比如scrapy(一个crawler framework),你只需定义好抓取的规则,抓好的数据怎么存储,它就能并发地帮你抓取并格式化数据。最有节操的是,它还提供了一个美妙的shell,让你在其中交互式地不断试错,直到可以正确定义好抓取的规则。

并发(concurrency)支持

在2.3里python有了generator,它是coroutine的基石。generator允许你挂起当前的执行点,使得同步的代码转为异步,顺序执行的程序具备潜在并行执行(Parallelism)的能力,比如说我们做个fabonacci数列:

def fabonacci():
    a, b = 1, 2
    while True:
        a, b = b, a+b
        yield b

通过generator,代码一下子具备了lazy evaluation的能力,只有在你需要的时候,数据才被计算出来。也许你在这里看不到并发的影子,那么请你想象一下满是generator的世界,每个generator都有自己的执行栈,如果你写个scheduler,将generator调入调出,这不就是coroutine么?当然,python有自己的coroutine库,gevent,基于效率最高的libev。比如用gevent实现actor model(erlang的基石):

import gevent
from gevent.queue import Queue

class Actor(gevent.Greenlet):

    def __init__(self):
        self.inbox = Queue()
        Greenlet.__init__(self)

    def receive(self, message):
        raise NotImplemented()

    def _run(self):
        self.running = True

        while self.running:
            message = self.inbox.get()
            self.receive(message)

简单,明了。

Python的缺陷

好吧,任何语言总有其阴暗面。Python(CPython)有个臭名昭著的GIL(当然这也不是python独有的,ruby也有MRI),全局解释锁,任何代码的执行都必须先获得这个全局锁,当有IO操作时释放这把锁。有了这个全局锁,Python的threading实际上是一个虚假的概念,无论你有多少个thread,只能使用一个核。你可以做个threading的实验:

import threading

def dead_loop():
    while True:
        pass

# new dead loop thread
t = threading.Thread(target=dead_loop)
t.start()

# dead loop on main thread
dead_loop()

t.join()

以及multiprocessing的测试:

import multiprocessing

def dead_loop():
    while True:
        pass

# new dead loop process
p = multiprocessing.Process(target=dead_loop)
p.start()

# dead loop on main process
dead_loop()

p.join()

看看二者CPU占用率的差异。threading很不给力啊!

当然,你无须为此感到太悲观。多线程用不到Multicore的能力,但多进程可以,虽然多进程开销大些,但终究能多少弥补GIL带来的缺憾。

原文发布于微信公众号 - 程序人生(programmer_life)

原文发表时间:2014-04-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

两种编程高手

第一种工程师 给一段复杂的程序,比如有7个局部变量,5层循环和if嵌套,他能赤手空拳上阵,迅速领会程序意图、找到bug,不用借助任何工具甚至纸笔。 给一个复杂的...

1975
来自专栏恰同学骚年

[转] Agile Software Development 敏捷软件开发

  敏捷开发是一种软件开发方法,基于迭代和增量开发,通过自组织,跨团队,沟通协作完成开发工作。

1032
来自专栏深度学习那些事儿

学习C语言的必备书籍-从入门到精通

不同学校教材不通,大部分书都把C语言的基本内容讲出来了,不推荐谭浩强的C语言书,如果仅仅是当第一本C语言书是可以的。

3464
来自专栏vue学习

前言

underscore.js一直听说都是一个很经典的库,很适合新手入门,所以历经小半年断断续续的学习,总算是把它敲完了。然后又过了一段时间到了现在,回过头来,打算...

901
来自专栏程序人生 阅读快乐

Java编程思想-第4版

本书赢得了全球程序员的广泛赞誉,即使是最晦涩的概念,在Bruce Eckel的文字亲和力和小而直接的编程示例面前也会化解于无形。从Java的基础语法到最高级特性...

742
来自专栏Cloud Native - 产品级敏捷

从面向对象到函数式编程: 我们正在构建更成熟的关注点隔离生态系统

2016.11.17, 深圳, Ken Fang 在谈论关注点隔离生态系统前, 我想,首先需要谈谈 Procedure Programming, Functio...

19910
来自专栏企鹅号快讯

月薪数万的攻城狮带你了解到什么是C语言编程思想,原来这就是编程思想

什么是编程思想?答案可能很会复杂,但也可以很简单; 一句话来讲就是,用计算机来解决人们实际问题的思维方式,即编程思想; 编程就是为了解决实际中的问题,在思考如何...

2469
来自专栏Java成神之路

WEB前端开发成长指南

小 编注:相比起网页射击狮,操纵代码的前端攻城狮凭着双手在键盘巴拉巴拉敲出的字符,就能赋予二次元的静态页面生命,各种lovely 的~~fabulous的~~e...

1013
来自专栏斑斓

面向流的设计思想

作者 | 张逸 特别说明:本文包含大量代码片段,若要获得更好阅读观感,请点击文末“阅读原文”或访问我的博客。 响应式编程(Reactive Programmin...

3543
来自专栏牛客网

老虎证券 iOS一面

2@property (weak, nonatomic) id delegate;

1271

扫码关注云+社区