python challenge 32解题总结

python challenge 32网址: www.pythonchallenge.com/pc/rock/arecibo.html 好像是个游戏 每行没列前头都用数字表示本行本列各连续方块的个数 网页提示 Fill in the blanks !-- for warmup.txt -- 下载 http://www.pythonchallenge.com/pc/rock/warmup.txt Dimensions 9 9 Horizontal 2 1 2 1 3 1 5 7 9 3 2 3 2 2 3 2 2 3 2 Vertical 2 1 3 1 2 3 3 8 9 8 3 1 2 3 2 1 3 网上查了一下,这种根据行列连续块的信息还原点阵图的游戏有个专门的名称叫Nonogram 见 http://zh.wikipedia.org/zh-cn/Nonogram 完成程序的过程比较曲折: 1)一开始看到是9*9的小图,就直接用0-512枚举生成每行每列的可能, 然后用穷举的方式通过正则匹配测试,得到了画着上箭头的图 == http://www.pythonchallenge.com/pc/rock/up.html 此时得到的需要还原的图是 32*32 的大图,原来的生成每行每列可能排列的方法的效率太低,没法用了; 2)然后用非递归方式写出生成每行每列可能排列的新方法(genlist()),但是在进行穷举时,发现 需要穷举的次数是个天文数字了,根本不可能短时间内算出结果; 3)经过仔细研究,开始尝试先从现有的可能排列中得到能确定是留空还是填充的点,再根据这些点反过来再次过滤所有 可能以去掉不符合的排列,然后再根据保留下的可能排列再次得到能确定的新的留空/填充的点,再用这些点反过来 过滤掉不符合的排列,如此反复进行 确定留空/填充点- 过滤不符合排列- 确定新的留空/填充点,经过26次后 终于将32*32个点都确定,最终得到画着蟒蛇的图; 4)最初的程序需要执行近22秒,经过优化后,单独执行大概需要近2秒,基本满意。后来从攻略中看到了 通过递归生成每行每列可能排列的函数(genv()),稍微修改就拿来用了,比genlist()要快0.5秒。 现在的程序算这个32*32的蟒蛇图需要约1.5秒(test3())。 5)考虑到应该尽早的以行/列新确定的点为过滤条件减少对应列/行的可能排列,这样可以减少迭代次数,并且减少函数调用 将主要逻辑放在一起,经测试32*32需要约1.3秒(test4()) 根据蟒蛇图 == http://www.pythonchallenge.com/pc/rock/python.html ps: 值得注意是网页也给出了解出的蟒蛇图js代码( http://www.pythonchallenge.com/pc/rock/python.js ) 网页提示: Congrats! You made it through to the smiling python. Free as in Free speech , not as in free... 上面每个单词都认识,组合起来啥意思不知道:(,google之 搜 Free as in Free speech, not as in free 搜到第一条是 http://www.gnu.org/philosophy/free-sw.html 中的 Free software is a matter of liberty, not price. To understand the concept, you should think of free as in free speech, not as in free beer. 好像意思是说自由软件指权利上的自由而不是指免费。要理解这一点,你可以比较 自由演讲 和 免费啤酒 中的free的区别。 所以提示中 free... 中的 ... 指的是 beer == http://www.pythonchallenge.com/pc/rock/beer.html 源代码如下: def level_32(): def test3(width,height): UNKNOWN,FILL,EMPTY='?','1',' ' resovled=[[UNKNOWN for _ in xrange(width)] for _ in xrange(height)] totalnumber=width*height print totalnumber def genv(v,l,marks): '''递归方式获取可能的排列 v=描述串(tuple列表) l=行/列长度 marks=(填满,留空) ''' r=[] j=0 if v: if len(v)==1: j=1 for i in range(l+2-len(v)-sum(v)): ri=marks[1]*i+marks[0]*v[0]+marks[1]*(1-j) if j: rr=[marks[1]*(l-len(ri))] else: rr=genv(v[1:],l-len(ri),marks) r+=[ri+vv for vv in rr] return r else: return [marks[1]*l] # 非递归方式获取可能的排列,比上面递归方式的genv要慢一点 def genlist(dim,blocklist,marks=('1','0')): '''非递归方式获取可能的排列 dim=行/列长度 blocklist=描述串(tuple列表) marks=(填满,留空) ''' ret=[] blankcnt=dim-sum(blocklist) blockcnt=len(blocklist) idxl=[1 for i in xrange(blockcnt+1)] idxl[0]=0 idxl[-1]=blankcnt-(blockcnt-1) cur=len(idxl)-2 tmp=cur while tmp!=-1: tmpstr=''.join([ marks[1]*idxl[x]+marks[0]*blocklist[x] for x in range(blockcnt)]+[marks[1]*idxl[-1],]) ret.append(tmpstr) if idxl[-1]==0: # 需要进位 tmp=cur-1 # 上一位 while tmp!=-1: # tmp=-1 无位可进,说明列举完毕,退出 if idxl[tmp] blankcnt-(blockcnt-tmp-1)-sum(idxl[:tmp]): # 此位可以再增加1 idxl[tmp]+=1 for i in range(tmp+1,blockcnt): idxl[i]=1 idxl[-1]=blankcnt-sum( ...

阅读全文 »

从两道趣味题目看python的简洁性

本文给出了两道趣味题目的 python 解法,足以说明 python 的简洁和可爱

  

下面给出了两道趣味题:

  1. 题目1是要求算一任意长度字符串中不同的字符以及它的个数。
  2. 题目2是把一段字符串用“右起竖排”的古文格式输出。

都是针对字符串的操作,逻辑比较简单,灵活在对不同语言、语法的掌握程度。

看了大家用Java、C#、C++等语言的实现,总感觉牛刀杀鸡太麻烦,有兴趣的朋友可以自己写写看或者直接看原文的网友回复。最近一段时间 Python写的比较多,读到这些题目时候,就有一种跃跃欲试的冲动。因为我知道用Perl, Python, Ruby等动态语言来做这类题目,会是非常理想的。后来我做了这两道题目,结果也令人满意,代码之简洁保持在所有答案的前列。

先看第一题:

dic = {}
for s in "abcdefgabc":
    dic[s] = 1 if s not in dic else (dic[s]+1)
print 'n'.join('%s,%s' % (k, v) for k, v in dic.items())

输出结果:

a,2
c,2
b,2
e,1
d,1
g,1
f,1

四行代码分别做了dictionary的声明,赋值,字符串的遍历,以及高效拼接。

如果还没有看出它的简洁和强大的话,请看第二题的解法:

def main(offset=6):
    string = u'静夜思 李白床前明月光,疑似地上霜。举头望明月,低头思故乡。090131'
    a = [[' ']*offset for row in xrange(offset)]
    for i in xrange(offset):
        for j in xrange(offset):
            a[i][j] = string[j + i*offset]
    b = [[r[col] for r in a[::-1]] for col in xrange(len(a[0]))]
    print 'n'.join([u'┊'.join(unicode(c) for c in row)for row in b])

输出结果:

0┊低┊举┊疑┊床┊静
9┊头┊头┊似┊前┊夜
0┊思┊望┊地┊明┊思
1┊故┊明┊上┊月┊ 
3┊乡┊月┊霜┊光┊李
1┊。┊,┊。┊,┊白

这题如果用C#等实现,代码要在20行以上。下面我简单介绍一下这几行代码:

  1. 第3行,在Python里面二维“数组”通过嵌套list来实现,这里初始化一个6行6列的二维数组;
  2. 第7行,我们把“矩阵”顺时针旋转了90度(行列置换,并且对置换后的行首尾对调-这里的::-1就是用来置换一个list的 trick);
  3. 最后一行,我们把数组里的每行中元素,每行之间分别用两个不同字符拼接起来。join方法以及for..in..语句在python中是 相当常见的用法。

通过这两题,我们看到Python在处理字符串时候的十分灵活方便,虽然一种语言的好坏不应完全靠是否简洁来衡量,但对于我个人而言,Python 是目前我用过的最好的语言。而且对于趣味题来说,这不就是我们解题的趣味所在吗?

阅读全文 »

enumerate初识

一直在研究怎么写代码更加pythonic,今天在读《The Python Standard Library》的时候重新研究了一下内置的函数enumerate(): enumerate(sequence[, start=0]) )返回一个枚举对象,sequence必须是一个序列、迭代器或者具有具有迭代功能的对象。enumerate()是适用于获得索引集:(0, seq[0]), (1, seq[1]), (2, seq[2]), .... 以前处理序列的时候经常使用以前写C的风格: [c] for (int i = 0; i < list.Length; i++) { //todo with list[i] } [/c] 于是在用python写代码的时候就习惯使用: [python] for i in range(len(sequence)): process(sequence[i]) [/python] 看了内置的函数enumerate后,发现以后处理就直接可以: [python] for i,element in enumerate(sequence): process(i,element) [/python]

阅读全文 »

Good to Great Python reads

A col­lec­tion of python “must reads”: The Python yield key­word explained Python’s super() con­sid­ered super! Under­stand­ing Python Decorators What is a meta­class in Python? Meta­classes Demystified Try/Catch for val­i­da­tion or speed? Python (and Python C API): __new__ ver­sus __init__ Python “self” keyword Python and the Prin­ci­ple of Least Astonishment A Curi­ous Course on Corou­tines and Concurrency Gen­er­a­tor Tricks for Sys­tems Programmers Code like a Python­ista: Idiomatic Python (2007) The entire Python Mod­ule of the week archive Also see the book — “ Python Stan­dard Library by Exam­ple ” (By me) Python Threads and the global inter­preter lock (By me) Get with the pro­gram as con­text manager How to write a Lisp inter­preter in Python Uni­code in Python, Com­pletely Demystified Uni­code for Dum­mies — Just use UTF-8 Debug­ging in Python How to han­dle mul­ti­ple inher­i­tance of ABCs that imple­ment each oth­ers abstract methods AOSA: Python Packaging 10 Rea­sons Python Rocks for Research (And a Few Rea­sons it Doesn’t) Beej’s Guide to Net­work Programming How to use Linux epoll with Python Python beginner’s Mistakes Com­mand Line syn­tax: Some basic Concepts Be care­ful with exec and eval in Python Dec­o­ra­tors make magic easy The detailed guide to “Tim­sort” (which Java adopted, FWIW) Notes on opti­miz­ing dictionaries How-to guide for Python Descriptors Python is Not Java (2004) Java is not Python, either Python Inter­faces are not Java Interfaces Begin­ner Python: http://wiki.python.org/moin/BeginnersGuide/Programmers A crash course into Python Python Style: PEP8: The Python Style Guide Python Books: Learn Python the Hard Way Dive into Python 3 A Byte of Python Port­ing to Python 3: An in-depth Guide Python Videos: Python Miro Com­mu­nity This con­tains hun­dreds of videos from Python con­fer­ences all over the world includ­ing past PyCons. Python Classes: Inter­me­di­ate and Advanced Soft­ware Car­pen­try in Python (2007) Google’s Python class Intro­duc­tion to Algo­rithms (with Python) Python Inter­nals: Python’s Innards: Introduction Python’s Innards: Objects 101 Python’s Innards: Objects 102 ( And the cor­rec­tion ) Python’s Innards: Pystate Python’s Innards: Naming Python’s Innards: Code Objects Python’s Innards: Inter­preter Stacks Python’s Innards: Hello, ceval.c Python His­tory: Guido Van Rossum’s “Python His­tory” blog (all of it!) Inter­faces or Abstract Base Classes (2005) Of Python and Road Maps (or the lack thereof) PyPy: Tuto­r­ial: Writ­ing an Inter­preter with PyPy Part 1 Tuto­r­ial: Writ­ing an Inter­preter with PyPy Part 2: Adding a JIT ...

阅读全文 »

python测试框架总结

If you are a developer or tester using Python, you live in exciting, ebullient times. There are Python-based testing frameworks newly-announced or recently-updated almost every day. Here is a rundown of the latest I'm aware of: 如果你是一个python开发人员或者python测试人员,令人沸腾的时刻到来了。这里介绍了许多python测试框架,它们或是最新发布的或者是最近都在保持更新的。下面就是我所知道的一些框架的列表: Unit testing 单元测试 py.test : no recent new release, but changes are happening almost daily in svn py.test :没有最近的新版本,但变化正在发生,几乎每天都在SVN.(目前最新的版本是2.2.0) TestOOB : version 1.16 was released on 2009 (TestOOB is an enhancement to the standard unittest module, offering many features that py.test offers) TestOOB :1.16版本发布于2009,以后没有更新。TestOOB是一个标准的unittest模块的增强,提供了许多功能,这些功能py.test也提供。 nose : version 1.1.2 was freshly released 0n 2011.7.13 (nose provides an alternate test discovery and running process for unittest, one that is intended to mimic the behavior of py.test as much as is reasonably possible without resorting to too much magic) nose :version 1.1.2 是发布于 0n 2011.7.13(nose为unittest提供另一种测试发现和测试处理的替代方式,它希望能够尽可能合理地和适度地模仿py.test,而不是采用太多具有魔力的方式) Web application testing web应用测试 twill : version 0.7.4 was released on Thursday, December 27th, 2007( twill is a simple language that allows users to browse the Web from a command-line interface. With twill, you can navigate through Web sites that use forms, cookies, and most standard Web features.) twill : version 0.7.4是在2007年12月27日星期四发布的。(twill是一种简单的语言,使用户能够从一个命令行界面的浏览网络。使用twill,您可以通过使用用户表单,临时文件,和最标准的Web功能。) FunkLoad : version 1.6.1 was released on 2011-07-28 (FunkLoad offers functional, performance, load and stress testing of Web applications) FunkLoad :version 1.6.1在2011-07-28上发布的(FunkLoad提供Web应用程序的功能,性能,负载和压力测试) zope.testbrowser : version 4.0.2 was released on 2011-05-25 (zope.testbrowser is the stand-alone version of the Zope 3 functional testing framework) zope.testbrowser: version 4.0.2 发布于2011-05-25(zope.testbrowser是Zope3功能测试框架的独立版本) Django's own doctest-based test framework: 目前python的web框架都或多或者提供了测试框架这里就不再一一说明了。 GUI testing 界面测试 guitest : version 0.31 was released on 2005 (guitest is a Python helper library for testing Python GUI applications, with pyGTK support being the most mature) guitest :version 0.31于2005年发布,以后没有更新。(guitest是一个用于测试python GUI应用的python辅助库,对pyGTK的支持是最成熟的,最适合于测试pyGTK应用。) Various 其他 retest(re-try) : version 0.6.1 was released on 2006 (retest enables tests of Python regular expressions in a webbrowser; it uses SimpleHTTPServer and AJAX) retest(re-try) :version 0.6.1发布于2006年,2009年更名为re-try,并且发布0.7.0(retest能够用于在浏览器上测试python的正则表达式,它使用了SimpleHTTPServer and AJAX) I also want to mention MochiKit as an example of an application that makes it a point to offer top-notch tests and documentation. MochiKit is a JavaScript library that is very "Pythonical" in nature, which is not surprising given that one of its main developers is Bob Ippolito , well-known for his contributions in the Python community. One of the goals of MochiKit is to maintain 100% documentation coverage , and ano ...

阅读全文 »

python开发规范(Guido van Rossum&&Barry Warsaw )(PEP8)

这份规范是python编程者必看的一份文档,最初是来自python之父的Guido van Rossum的python风格指南,官方的编号为PEP:8,原始地址为:http://www.python.org/dev/peps/pep-0008/
PEP: 8
Title: Style Guide for Python Code
Version: 00f8e3bb1197
Last-Modified: 2011-06-13 12:48:33 -0400 (Mon, 13 Jun 2011)
Author: Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>
Status: Active
Type: Process
Created: 05-Jul-2001
Post-History: 05-Jul-2001
    中文版请见PDF附件:Python开发编码规范(本文的翻译是由 hoxide、dreamingk、xyb、RedWolf 完成)

阅读全文 »

如何成为Python高手(How to become a proficient Python programmer )

本文是从 How to become a proficient Python programmer 这篇文章翻译而来。 这篇文章主要是对我收集的一些文章的摘要。因为已经有很多比我有才华的人写出了大量关于如何成为优秀Python程序员的好文章。 我的总结主要集中在四个基本题目上:函数式编程,性能,测试,编码规范。如果一个程序员能将这四个方面的内容知识都吸收消化,那他/她不管怎样都会有巨大的收获。 函数式编程 命令式的编程风格已经成为事实上的标准。命令式编程的程序是由一些描述状态转变的语句组成。虽然有时候这种编程方式十分的有效,但有时也不尽如此(比如复杂性) —— 而且,相对于声明式编程方式,它可能会显得不是很直观。 如果你不明白我究竟是在说什么,这很正常。这里有一些文章能让你脑袋开窍。但你要注意,这些文章有点像《骇客帝国》里的红色药丸 —— 一旦你尝试过了函数式编程,你就永远不会回头了。 http://www.amk.ca/python/writing/functional http://www.secnetix.de/olli/Python/lambda_functions.hawk http://docs.python.org/howto/functional.html 性能 你会看到有如此多的讨论都在批评这些“脚本语言”(Python,Ruby)是如何的性能低下,可是你却经常的容易忽略这样的事实:是程序员使用的算法导致了程序这样拙劣的表现。 这里有一些非常好的文章,能让你知道Python的运行时性能表现的细节详情,你会发现,通过这些精炼而且有趣的语言,你也能写出高性能的应用程 序。而且,当你的老板质疑Python的性能时,你别忘了告诉他,这世界上第二大的搜索引擎就是用Python写成的 —— 它叫做Youtube(参考 Python摘录 ) http://jaynes.colorado.edu/PythonIdioms.html http://wiki.python.org/moin/PythonSpeed/PerformanceTips 测试 如今在计算机科学界,测试可能是一个最让人不知所措的主题了。有些程序员能真正的理解它,十分重视TDD(测试驱动开发)和它的后继者BDD(行为 驱动开发)。而另外一些根本不接受,认为这是浪费时间。那么,我现在将告诉你:如果你不曾开始使用TDD/BDD,那你错过了很多最好的东西! 这并不只是说引入了一种技术,可以替换你的公司里那种通过愚蠢的手工点击测试应用程序的原始发布管理制度,更重要的是,它是一种能够让你深入理解你 自己的业务领域的工具 —— 真正的你需要的、你想要的攻克问题、处理问题的方式。如果你还没有这样做,请试一下。下面的这些文章将会给你一些提示: http://www.oreillynet.com/lpt/a/5463 http://www.oreillynet.com/lpt/a/5584 http://wiki.cacr.caltech.edu/danse/index.php/Unit_testing_and_Integration_testing http://docs.python.org/library/unittest.html 编码规范 并非所有的代码生来平等。有些代码可以被另外的任何一个好的程序员读懂和修改。但有些却只能被读,而且只能被代码的原始作者修改 —— 而且这也只是在他或她写出了这代码的几小时内可以。为什么会这样?因为没有经过代码测试(上面说的)和缺乏正确的编程规范。 下面的文章给你描述了一个最小的应该遵守的规范合集。如果按照这些指导原则,你将能编写出更简洁和漂亮的代码。作为附加效应,你的程序会变得可读性更好,更容易的被你和任何其他人修改。 http://www.python.org/dev/peps/pep-0008/ http://www.fantascienza.net/leonardo/ar/python_best_practices.html 那就去传阅这这些资料吧。从坐在你身边的人开始。也许在下一次程序员沙龙或编程大会的时候,也已经成为一名Python编程高手了! 祝你学习旅途顺利。 如果你喜欢这些文章,请在微博上顶一下,让其他人也知道。 本文原始地址: 如何成为Python高手 ...

阅读全文 »

Beautiful Soup 中文文档之二

剖析 HTML 使用 BeautifulSoup 类剖析HTML文档。 BeautifulSoup会得出以下一些信息: 有些标签可以内嵌 如:BLOCKQUOTE,有些不行 如:P table和list标签有一个自然的内嵌顺序。例如,TD标签内为TR标签,而不会相反。 SCRIPT 标签的内容不会被剖析为HTML。 META 标签可以知道文档的编码类型。 这是运行例子: 这是运行例子: from BeautifulSoup import BeautifulSoup html = " html p Para 1 p Para 2 blockquote Quote 1 blockquote Quote 2" soup = BeautifulSoup ( html ) print soup . prettify () # html # p #   Para 1 # /p # p #   Para 2 # blockquote #    Quote 1 # blockquote #     Quote 2 # /blockquote # /blockquote # /p # /html 注意: BeautifulSoup 会智能判断那些需要添加关闭标签的位置,即使原始的文档没有。 也就是说那个文档不是一个有效的HTML,但是它也不是太糟糕。下面是一个比较糟糕的文档。在一些问题中,它的 FORM 的开始在 TABLE 外面,结束在 TABLE 里面。 (这种HTML在一些大公司的页面上也屡见不鲜) from BeautifulSoup import BeautifulSoup html = """ html form table td input name="input1" Row 1 cell 1 tr td Row 2 cell 1 /form td Row 2 cell 2 br This /br sure is a long cell /body /html """ Beautiful Soup 也可以处理这个文档: print BeautifulSoup ( html ). prettify () # html # form # table # td # input name="input1" / #     Row 1 cell 1 # /td # tr # td #      Row 2 cell 1 # /td # /tr # /table # /form # td #   Row 2 cell 2 # br / #   This #   sure is a long cell # /td # /html table的最后一个单元格已经在标签 TABLE 外了;Beautiful Soup 决定关闭 TABLE 标签当它在 FORM 标签哪里关闭了。写这个文档家伙原本打算使用 FORM 标签扩展到table的结尾,但是Beautiful Soup 肯定不知道这些。即使遇到这样糟糕的情况, Beautiful Soup 仍可以剖析这个不合格文档,使你开业存取所有数据。 剖析 XML BeautifulSoup 类似浏览器,是个具有启发性的类,可以尽可能的推测HTML文档作者的意图。但是XML没有固定的标签集合,因此这些启发式的功能没有作用。因此 BeautifulSoup 处理XML不是很好。 使用 BeautifulStoneSoup 类剖析XML文档。它是一个概括的类,没有任何特定的XML方言已经简单的标签内嵌规则。下面是范例: from BeautifulSoup import BeautifulStoneSoup xml = " doc tag1 Contents 1 tag2 Contents 2 tag1 Contents 3" soup = BeautifulStoneSoup ( xml ) print soup . prettify () # doc # tag1 #   Contents 1 # tag2 #    Contents 2 # /tag2 # /tag1 # tag1 #   Contents 3 # /tag1 # /doc BeautifulStoneSoup 的一个主要缺点就是它不知道如何处理 自结束标签 。 HTML 有固定的自结束标签集合,但是XML取决对应的DTD文件。你可以通过传递 selfClosingTags 的参数的名字到 BeautifulStoneSoup 的构造器中,指定自结束标签: from BeautifulSoup import BeautifulStoneSoup xml = " tag Text 1 selfclosing Text 2" print BeautifulStoneSoup ( xml ). prettify () # tag #  Text 1 # selfclosing #   Text 2 # /selfclosing # /tag print BeautifulStoneSoup ( xml , selfClosingTags =[ 'selfclosing' ]). prettify () # tag #  Text 1 # selfclosing / #  Text 2 # /tag 如果它不工作 这里有 一些其他的剖析类 使用与上述两个类不同的智能感应。你也可以 子类化以及定制一个剖析器 使用你自己的智能感应方法。 使用Unicode的Beautiful Soup,Dammit 当你的文档被剖析之后,它就自动被转换为unicode。 Beautiful Soup 只存储Unicode字符串。 from BeautifulSoup import BeautifulSoup soup = BeautifulSoup("Hello") soup.contents[0] # u'Hello' soup.originalEncoding # 'ascii' 使用UTF-8编码的日文文档例子: from BeautifulSoup import BeautifulSoup soup = BeautifulSoup("xe3x81x93xe3x82x8cxe3x81xaf") soup.contents[0] # u'u3053u308cu306f' soup.originalEncoding # 'utf-8' str(soup) # 'xe3x81x93xe3x82x8cxe3x81xaf' # Note: this bit uses EUC-JP, so it only works if you have cjkcodecs # installed, or are running Python 2.4. soup.__str__('euc-jp') # 'xa4xb3xa4xecxa4xcf' Beautiful Soup 使用一个称为 UnicodeDammit 的类去来检测文档的编码,并将其转换为Unicode。如果你需要为其他文档(没有石油Beautiful Soup剖析过得文档)使用这转 ...

阅读全文 »

Python 悖论

日前, 我提到 Python 程序员要比使用 Java 工作的程序员更聪明。大家也许会有点疑惑吧。 我并没有 "Java 程序员何其盲目" 的意思, 我只想说 Python 程序员是很聪明的。学习一种新的编程语言都是需要花点工夫的 ──── 而 Python 并不能用来找工作。人们学习 Python 只是因为他们率真地喜欢编程, 而目前所有已知的编程语言都不能使他们满足。 这使得这种程序员成为软件公司心目中最为理想的雇员。介于此, 目前还没有一个更好的词, 我姑且叫它 Python 悖论吧: 如果公司选用一种颇为曼妙的编程语言, 他能雇到好的程序员, 因为好的编程语言总是能够吸引到优秀的程序员。然后悖论就来了: 这种语言会很快流行, 会有许多工作机会, 然后这种语言 (比如 Java) 就堕落成程序员的敲门砖了。 只有少数公司能够清醒地认识到这一点。但是还有另一种可能, 就是公司里的程序员都非常热爱他们的编程工作于是一拍即合, 从而逃离这个悖论的影响。Google, 比如说。当他们刊登招聘 Java 程序员的广告时, 同时也要求有 Python 的编程经历。 我有一个几乎懂得所有编程语言的朋友, 几乎所有的项目他都在使用 Python。据他自己说主要是因为, "他喜欢 Python 源代码在视觉感官上的体验"。对于语言的选择, 这是一个看似非常轻佻的理由。但它实际上并没有听上去那么卤莽: 当你编程时, 比起书写代码你得花更多的时间去阅读它们。如同雕塑家将泥一块一块地涂到艺术品上, 你的代码被一行一行地添加上去。因此, 如果一种语言写出的代码不那么漂亮, 它会让严谨的程序员抓狂, 恰如一位雕塑家看到一个充满瑕疵的作品一样。 既然提到了丑陋的代码, 许多人理所当然地会想到 Perl。但是 Perl 代码的丑陋只是表象, 并不是我所说的那种丑陋的类型。真正的丑陋不是肤浅地从字面代码上来评判, 而是你被迫基于一种错误的观念来架构你的程序。也许看上去 Perl 像是 "$%^ $#@! ...", 但是有许多案例证明他其实拥有比 Python 更先进的理念。 迄今为止, 不管怎么说。这两种语言尽管设计的目标不同, 但是它们, 包括 Ruby (以及 Icon, Joy, J, Lisp, 和 Smalltalk) 都是为那些真正关心程序的人创建, 并给他们使用的。这是事实。这些程序员总会试图去做得更好。 The Python Paradox August 2004 (原文地址: http://www.paulgraham.com/pypar.html) In a recent talk I said something that upset a lot of people: that you could get smarter programmers to work on a Python project than you could to work on a Java project. I didn't mean by this that Java programmers are dumb. I meant that Python programmers are smart. It's a lot of work to learn a new programming language. And people don't learn Python because it will get them a job; they learn it because they genuinely like to program and aren't satisfied with the languages they already know. Which makes them exactly the kind of programmers companies should want to hire. Hence what, for lack of a better name, I'll call the Python paradox: if a company chooses to write its software in a comparatively esoteric language, they'll be able to hire better programmers, because they'll attract only those who cared enough to learn it. And for programmers the paradox is even more pronounced: the language to learn, if you want to get a good job, is a language that people don't learn merely to get a job. Only a few companies have been smart enough to realize this so far. But there is a kind of selection going on here too: they're exactly the companies programmers would most like to work for. Google, for example. When they advertise Java programming jobs, they also want Python experience. A friend of mine who knows nearly all the widely used languages uses Python for most of his projects. He says the main reason is that he likes the way source code looks. That may seem a frivolous reason to choose one language over another. But it is not so frivolous as it sounds: when you program, you spend more time reading code than writing it. You push blobs of source code around the way a sculptor does blobs of clay. So a language that makes source code ugly is maddening to an exacting programmer, as clay full of lumps would be to a sculptor. At the mention of ugly source code, people will of course th ...

阅读全文 »

python程序员的进化(The Evolution of a Python Programmer )

不久前,在互联网上出现了一篇有趣的文章,讲的是对于同一个问题,不同层次的程序员编出的Python代码显示出了不同的风格,代码都很简单,有趣。这篇文章的原始出处在 这里 ,我把它整理了一下,并修改了几处错误。 编程新手 1 2 3 4 5 6 def factorial ( x ) : if x == 0 : return 1 else : return x * factorial ( x - 1 ) print factorial ( 6 ) 一年编程经验(学Pascal的) 1 2 3 4 5 6 7 8 def factorial ( x ) : result = 1 i = 2 while i = x: result = result * i i = i + 1 return result print factorial ( 6 ) 一年编程经验(学C的) 1 2 3 4 5 6 7 8 9 def fact ( x ) : #{ result = i = 1 ; while ( i = x ) : #{ result * = i ; i += 1 ; #} return result ; #} print ( fact ( 6 ) ) 一年编程经验(读过 SICP ) 1 2 3 4 5 @tailcall def fact ( x, acc= 1 ) : if ( x 1 ) : return ( fact ( ( x - 1 ) , ( acc * x ) ) ) else : return acc print ( fact ( 6 ) ) 一年编程经验(Python) 1 2 3 4 5 6 def Factorial ( x ) : res = 1 for i in xrange ( 2 , x + 1 ) : res * = i return res print Factorial ( 6 ) 懒惰的Python程序员 1 2 3 def fact ( x ) : return x 1 and x * fact ( x - 1 ) or 1 print fact ( 6 ) 更懒的Python程序员 1 2 f = lambda x: x and x * f ( x - 1 ) or 1 print f ( 6 ) Python 专家 1 2 fact = lambda x: reduce ( int . __mul__ , xrange ( 2 , x + 1 ) , 1 ) print fact ( 6 ) Python 黑客 1 2 3 4 5 6 import sys @tailcall def fact ( x, acc= 1 ) : if x: return fact ( x. __sub__ ( 1 ) , acc. __mul__ ( x ) ) return acc sys . stdout . write ( str ( fact ( 6 ) ) + ' n ' ) 专家级程序员 1 2 from c_math import fact print fact ( 6 ) 大英帝国程序员 1 2 from c_maths import fact print fact ( 6 ) Web 设计人员 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def factorial ( x ) : #------------------------------------------------- #--- Code snippet from The Math Vault --- #--- Calculate factorial (C) Arthur Smith 1999 --- #------------------------------------------------- result = str ( 1 ) i = 1 #Thanks Adam while i = x: #result = result * i #It's faster to use *= #result = str(result * result + i) #result = int(result *= i) #?????? result = str ( int ( result ) * i ) #result = int(str(result) * i) i = i + 1 return result print factorial ( 6 ) Unix 程序员 1 2 3 4 import os def fact ( x ) : os . system ( 'factorial ' + str ( x ) ) fact ( 6 ) Windows 程序员 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 NULL = None def CalculateAndPrintFactorialEx ( dwNumber, hOutputDevice, lpLparam, lpWparam, lpsscSecurity, * dwReserved ) : if lpsscSecurity ! = NULL: return NULL #Not implemented dwResult = dwCounter = 1 while dwCounter = dwNumber: dwResult * = dwCounter dwCounter += 1 hOutputDevice. write ( str ( dwResult ) ) hOutputDevice. write ( ' n ' ) return 1 import sys CalculateAndPrintFactorialEx ( 6 , sys . stdout , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) 企业级程序员 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 def new ( cls, * args, ** kwargs ) : return cls ( * args, ** kwargs ) class Number ( object ) : pass class IntegralNumber ( int , Number ) : def toInt ( self ) : return new ( int , self ) class InternalBase ( object ) : def __init__ ( self , base ) : self . base = base. toInt ( ) def getBase ( self ) : return n ...

阅读全文 »