前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[技术] 谈谈Python

[技术] 谈谈Python

作者头像
tyrchen
发布2018-03-28 14:36:44
8770
发布2018-03-28 14:36:44
举报
文章被收录于专栏:程序人生程序人生

昨天的文章收获了不少有价值的回复。不少人发现了一个大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。我所了解的任何一门其他语言都没有如此巧妙而又大张旗鼓地将其文化写入了语言本身。

代码语言:javascript
复制
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,打开一看,一段格式熟悉,但乱七八糟的文字,然后是一段代码:

代码语言:javascript
复制
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努力的方向):

代码语言:javascript
复制
with open('hello.txt') as f:
    f.write('Hello world!\n')

这等价于之前的写法:

代码语言:javascript
复制
f = open('hello.txt')
try:
    f.write('Hello world!\n')
finally:
    f.close()

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

代码语言:javascript
复制
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的撰写简直就像写文章一样简单直观:

代码语言:javascript
复制
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数列:

代码语言:javascript
复制
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的基石):

代码语言:javascript
复制
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的实验:

代码语言:javascript
复制
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的测试:

代码语言:javascript
复制
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带来的缺憾。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2014-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文化和关怀
  • 应用场景
  • 语言能力
  • 有意思的库和工具
  • 并发(concurrency)支持
  • Python的缺陷
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档