我推荐Python的理由

标签:Python

在家闲得无聊,写了东西,希望能吸引几个Pythoner。

习惯了静态语言,当年的我也觉得C++就是不二选择了。即便到了大学毕业,陆陆续续掌握了10多种语言,也依然没有改变我这个看法。
我的观点也一直很明确:作为一位专业的程序员,第一门应该精通的语言是C,接着应该掌握汇编语言,之后再学什么语言都可以融会贯通。
特别值得一提的是Java:我毕业论文是靠它完成的,工作中首要使用的语言也是它,可除了库多和自动内存管理外,我在平常的应用中实在找不到什么优势。而由于不支持运算符重载和默认参数,在语法层面上就得多写很多繁琐的代码。

然而自从接触了JavaScript这种动态语言,我才猛然发现静态语言的不足,并转向这个更为美丽的阵营。
如今我略知一二的动态语言有这几种:JavaScript、Python、Ruby和Lua,而Python则是我唯一推荐的。
这并不是说其他的语言不好,而是说如果你只想学一门语言,那么Python就是最好的选择。

当然,绝大多数人不会同意我的看法,所以我会一一将理由列出。

首先看下比较泛泛而谈的方面:
  1. 快速上手。Python的书籍非常多,文档也很详细,大多数模块都配有例子。我不知道初学编程的人要多久才能掌握Python,但我只用了半天就掌握了大部分Python的语法。你完全可以在等公交或挤地铁时学会Python。
  2. 用途广泛。如果不考虑性能,你几乎可以用Python做任何事,包括系统编程、数据库、应用软件、游戏、WEB应用等等。
  3. 平台无关。从嵌入式设备到几十年前的大型机上你都能找到Python,它支持的平台甚至多于Java。
  4. 模块众多。无论你是想操作数据库,还是想进行音乐、图像处理,或者处理文字编码解码,Python都在标准库里为你提供了。而且不但标准库不逊于Java,就连第三方库的数量也没有哪门语言可以比得上,并且这些库大多是开源和免费的。
  5. 使用方便,无需编译。打开命令行,敲入Python就能在控制台直接执行Python语句了。用文本编辑器编辑一个.py文件,编写完双击它就能运行了。在构建较大的应用时会节约很多时间,即便是Java这种语言,在打个par或war包时,仍然需要几分钟的编译和构建时间。
  6. 代码简短,容易阅读。由于内置了众多实用的类型,合理的操作符重载,以及各种语法特性和库的支持,实现同样的事,Python几乎总比绝大部分语言少写很多代码。
  7. 面向对象。如今大多数语言都已在语法层面上支持面向对象了,所以这或许算不上什么。只是想和Ruby拥护者强调一下,Python同样也是纯面向对象的语言。Python里所有你能看到的东西,全都是对象,包括1、2、3这种字面量,甚至代码和栈帧。至于Python里有函数,所以不是纯面向对象的这种说法也是站不住脚的:因为函数也是对象,一个函数调用就是将0到多个对象传递给函数对象的__call__方法的过程,难道非得加个小数点才叫面向对象?
接着看看一些值得一提的特性:
  1. 支持长整数类型,长度只受限于虚拟内存的大小。
    例如123的321次方:
    >>> 123 ** 321
    72367033806371673149109894141163778628811792657571658906010558390395870363798401
    74409528068615550773640492165707028496172182896059297790954263709889769722310262
    26285667876540913278254539915951402057014129613641887324089361978905536997158369
    51569999800431957769217006743321026257517932764164662319487914962533302741368207
    21118949461532655279066772041128547416263676516890721192413497337430449601963537
    66658585599417357039248364677569172479954695834874677915245821537445221075978652
    77798136080074161485280424274076931083994487111719562249702540362855712911132265
    96623575435535351670333904300150611852076035957773786947201861794212059087317071
    0805078696371738906375721785723L
  2. 支持连续比较。
    >>> 10 > 5 > 3
    True
    >>> 10 < 15 > 3
    True
    >>> 10 > 2 < 3
    True
  3. 快速生成列表。
    例如0~100之间所有的奇数:
    >>> range(1, 100, 2)
    [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,
    43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81,
    83, 85, 87, 89, 91, 93, 95, 97, 99]
  4. 列表支持切片操作。
    >>> x = range(20, 0, -1)
    >>> x
    [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
    >>> x[8:] # 生成x的第8到最后一个元素的列表
    [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
    >>> x[:8] # 生成x的第0到第8个(不包含第8)元素的列表
    [20, 19, 18, 17, 16, 15, 14, 13]
    >>> x[:-8] # 生成x的第0到倒数第8个元素的列表
    [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9]
    >>> x[8:-8] # 生成x的第8到倒数第8个元素的列表
    [12, 11, 10, 9]
    >>> x[::2] # 从x中每隔1个数生成的列表
    [20, 18, 16, 14, 12, 10, 8, 6, 4, 2]
    >>> x[8:-8:2] # x的第8到倒数第8个元素中,每隔1个数生成的列表
    [12, 10]
  5. 元组可以自动打包和解包。
    >>> a, b = 1, 2
    >>> a
    1
    >>> b
    2
    >>> a, b = b, a
    >>> a
    2
    >>> b
    1
    >>> def f():
    ...   return 3, 4 # 函数可以返回多个值,实际上也是元组
    ...
    >>> a, b = f()
    >>> a
    3
    >>> b
    4
    >>> a = f()
    >>> a
    (3, 4)
  6. 强大的for循环让大多数情况下无需处理循环索引。
    例如计算0~100的奇数和:
    >>> s = 0
    >>> for i in range(1, 100, 2):
    ...   s += i # 每次迭代,i都会被赋予下一个值
    ...
    >>> s
    2500
    还可以同时获得多个迭代值:
    >>> x = (((1, 2), 3),)
    >>> x *= 5
    >>> x
    (((1, 2), 3), ((1, 2), 3), ((1, 2), 3), ((1, 2), 3), ((1, 2), 3))
    >>> for (i, j), k in x:
    ...   s += (i + j + k)
    ...
    >>> s
    30
  7. 可用zip函数同时迭代2个列表。
    >>> a = range(5)
    >>> b = range(5, 10)
    >>> zip(a, b)
    [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]
    >>> for x, y in zip(a, b):
    ...   print x + y,
    ...
    5 7 9 11 13
  8. 支持lambda函数。(不过不如Lisp的简洁,也没有JavaScript的匿名函数强大,更不如Ruby的block优雅)
    >>> f = lambda x: 2 * x
    >>> f(3)
    6
    >>> (lambda x: 2 * x)(3)
    6
    >>> map(lambda x: 2 * x, range(10))
    [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
    >>> filter(lambda x: x % 2, range(10))
    [1, 3, 5, 7, 9]
    >>> reduce(lambda x, y: x * y, range(1, 10))
    362880
  9. 列表解析可以省略很多for循环、map和filter函数。
    >>> [str(i) for i in range(10)]
    ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
    >>> [i * i for i in range(20) if i % 2 and i % 3 ]
    [1, 25, 49, 121, 169, 289, 361]
    >>> [i * j for i in range(5) for j in range(5, 10)]
    [0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 15, 18, 21, 24, 27, 20, 24, 2
    8, 32, 36]
    >>> [i * j for i in range(5) for j in range(5) if i > j]
    [0, 0, 2, 0, 3, 6, 0, 4, 8, 12]
  10. 支持缺省参数,且缺省参数位置随意。
    >>> def f(a, b=1, c=2):
    ...   return a + b + c
    ...
    >>> f(1)
    4
    >>> f(1, 2)
    5
    >>> f(1, c=5)
    7
    >>> f(1, c=5, b=9)
    15
    >>> f(c=5, a=8, b=9)
    22
  11. 支持参数列表和参数字典。
    >>> def f(a, b=1, c=2):
    ...   return a + b + c
    ...
    >>> args = [9, 8, 7]
    >>> f(*args)
    24
    >>> kwargs = zip(['a', 'b', 'c'], args)
    >>> kwargs
    [('a', 9), ('b', 8), ('c', 7)]
    >>> kwargs = dict(kwargs)
    >>> kwargs
    {'a': 9, 'c': 7, 'b': 8}
    >>> f(**kwargs)
    24
    >>> f(9, *[8], **{'c': 7})
    24
    >>> a = (0, 1, 2, 3, 4)
    >>> b = (5, 6, 7, 8, 9)
    >>> zip(a, b)
    [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]
    >>> zip(*zip(a, b))
    [(0, 1, 2, 3, 4), (5, 6, 7, 8, 9)]
    >>> c, d = zip(*zip(a, b))
    >>> c # 等于a
    (0, 1, 2, 3, 4)
    >>> d # 等于b
    (5, 6, 7, 8, 9)
  12. 支持闭包和高阶函数。
    >>> def f(x):
    ...   return  x + 1
    ...
    >>> def g(func):
    ...   def wrap(x):
    ...     return func(x) * 2
    ...   return wrap
    ...
    >>> h = g(f)
    >>> h(2)
    6
    >>> @g
    ... def a(x):
    ...   return x + 1
    ...
    >>> a(2)
    6
  13. 对象的属性和方法可以动态改变:
    >>> class A(object):
    ...   def __init__(self, x):
    ...     self.x = x
    ...
    >>> a = A(10)
    >>> a.x
    10
    >>> a.y
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'A' object has no attribute 'y'
    >>> a.y = 5
    >>> a.y
    5
    >>> del a.x
    >>> a.x
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'A' object has no attribute 'x'
    >>> def f(self):
    ...   return 10
    ...
    >>> A.x = f
    >>> a.x()
    10
  14. 对象的类型可以动态改变。
    >>> class A(object):
    ...   def __init__(self, x):
    ...     self.x = x
    ...   def y(self):
    ...     return self.x * 2
    ...
    >>> class B(object):
    ...   def __init__(self, x):
    ...     self.x = x
    ...   def y(self):
    ...     return self.x / 2
    ...
    >>> x = A(10)
    >>> x.y()
    20
    >>> x.__class__ = B
    >>> x.y()
    5
其他虽然还有很多优点,但我觉得不值得在这提出。为了公平起见,把部分缺点也列出。
  1. 性能不出色。比起静态语言要差很多,但是在动态语言里表现尚可,至少不逊色于Ruby和PHP。
    要追求性能,就不得不以C来重写这些实现;但好在绝大部分Python程序员不需要做这种事,也有较为方便的工具可以将Python(的一个变种)转换成C实现,并编译成机器语言。
  2. 不支持switch...case结构,只能以传统的if...elif...else来实现。
    不过Ruby虽说支持switch...case,但我估计内部实现也是if...elif...else(未考证)。
  3. 没有抽象类和接口,对象靠实现特殊的属性和方法来实现一个接口,但书写很麻烦(前后2个下划线)。
  4. 私有属性不是真正的私有(可以通过特殊的办法访问),且没有保护和包访问方式。
  5. 实例方法不能省略第一个self参数,内部也得使用“self.属性名”的方式来访问属性。
    这主要是因为Python的方法实现很奇特,实例方法、类方法和静态方法是用相同的机制实现的,这在部分情况下提供了便利。
  6. 不支持多行注释。只能靠编辑器来帮忙了。
  7. 内部函数不能改变外部函数的命名空间,包括赋值和删除。Python 2.x只能将其提升为global变量来解决,而Python 3.x者可以使用nonlocal。
  8. Python 3.x与Python 2.x不兼容,而大部分的库只支持Python 2.x,会导致初学者不知道该学哪个版本。

10条评论 你不来一发么↓ 顺序排列 倒序排列

    向下滚动可载入更多评论,或者点这里禁止自动加载

    想说点什么呢?