你真的了解Python吗?Python有哪些让你相见恨晚的小技巧呢?

一、前言

我前两天回答了两个Python相关的问题,收到了很多赞,从答案被收藏的情况来看,确实对不少人都很有帮助,所以我也很开心。我今天准备把这个问题认真回答一下。我会先讨论什么是优美的代码;然后,我会给出一些我压箱底的好东西;最后,我会讨论怎么写出优美的代码。

二、什么是优美(优雅)的代码

什么是优美或优雅的代码实现呢?在Python里面,我们一般称之为Pythonic。Pythonic并没有一个确切的定义,一直以来都是只能意会,不能言传的东西。为了帮助新同学理解,我对Pythonic给出了明确的定义:所谓Pythonic,就是用Python的方式写出简洁优美的代码

有了Pythonic以后,不同的工程师之间,也依然无法对优美的代码达成一致的意见。因为,美本身是一个主观感受,每个人对美的感受是不一样的。比如,有些人觉得汤唯更美,有些人觉得范冰冰最漂亮,还有些人居然喜欢AngelaBaby(一把年纪了叫baby你们不觉得怪吗?)。而我,依然最喜欢刘涛。我在这篇文章中,会给出很多具体的例子,来说明怎样写代码是'美'的,由于美是一种主观感受,所以,这里的回答可能会引起大家的争议。

另外,在这篇回答中,我们只讨论优美的Python代码实现,并不讨论Python中存在的坑。我估计Python里面有很多坑大家都没有注意到,比如:

    >>> a = 4.2
    >>> b = 2.1
    >>> print a+b == 6.3
    False

对于这个坑,如果有特别感兴趣的同学,可以看

深入理解计算机系统(原书第2版) (豆瓣)

的第二章。

三、优美的代码实现

在这一部分,我们会依次讨论一些美的代码。由于内容较多,所以,我进行了简单地分类,包括:

  1. 内置函数
  2. Python中的一些小细节
  3. 充分使用数据结构的便利性
  4. 合理使用Python的高级并发工具
  5. 巧妙使用装饰器简化代码
  6. Python中的设计模式

3.1 善用内置函数

enumerate类

enumerate是一个类,但是用起来却跟函数一样方便,为了表述方便,我们后面统称为函数。不使用enumerate可能是Python新手最容易被吐槽的地方了。enumerate其实非常简单,接收一个可迭代对象,返回index和可迭代对象中的元素的组合。

对于Python新手,推荐使用ipython(还有bpython和ptpython,感兴趣的同学也可以了解一下)交互式地测试各个函数的效果,并且,我们可以在函数后面输入一个问号,然后回车,就能够获得这个函数的帮助文档了。如下所示:

        In [1]: enumerate?
        Type:       type
        String Form:<type 'enumerate'>
        Namespace:  Python builtin
        Docstring:
        enumerate(iterable[, start]) -> iterator for index, value of iterable

        Return an enumerate object.  iterable must be another object that supports
        iteration.  The enumerate object yields pairs containing a count (from
        start, which defaults to zero) and a value yielded by the iterable argument.
        enumerate is useful for obtaining an indexed list:
            (0, seq[0]), (1, seq[1]), (2, seq[2]), ...

关于enumerate的效果,我们一起来看一下,你就知道为什么不使用enumerate会被吐槽了。这是不使用enumerate的时候,打印列表中的元素和元素在列表中的位置代码:

        from __future__ import print_function

        L = [ i*i for i in range(5) ]

        index = 0
        for data in L:
            index += 1
            print(index, ':', data)

这是使用enumerate的Python代码:

        from __future__ import print_function

        L = [ i*i for i in range(5) ]

        for index, data in enumerate(L):
            print(index + 1, ':',  data)

这是正确使用enumerate的姿势:

        from __future__ import print_function

        L = [ i*i for i in range(5) ]

        for index, data in enumerate(L, 1):
            print(index, ':',  data)

去除import语句和列表的定义,实现同样的功能,不使用enumerate需要4行代码,使用enumerate只需要2行代码。如果想把代码写得简洁优美,那么,大家要时刻记住:在保证代码可读性的前提下,代码越少越好。显然,使用enumerate效果就好很多。

reversed

对Python熟悉的同学知道,Python中的列表支持切片操作,可以像L[::-1]这样去reverse列表。如下所示:

        [1, 2, 3, 4]
        >>> for item in L[::-1]:
        ...     print(item)
        ...
        4
        3
        2
        1

与此同时,我们也可以使用内置的reversed函数,如下所示:

        >>> for item in reversed(L):
        ...     print(item)
        ...
        4
        3
        2
        1

我的观点是,L[::-1]不如使用reversed好,因为,L[::-1]是一个切片操作。我们看到这个代码的第一反应是序列切片,然后才是切片的效果是reverse列表。对于reversed函数,即使是刚接触Python的同学,也能够一眼看出来这个函数是要做什么事情。也就是说,实现同样的功能,L[::-1]比reversed多绕了一个弯。我们这个问题是如何写出优美的代码,而我认为,优美的代码就应该简洁、直接、少绕弯。

读者如果对我这里的解释表示怀疑的话,我表示理解。但是,我还是想劝你认可我的说法。因为我认为,不管我们使用代码还是文字,都是在表达某些东西。而我的表达能力,也是读研究生以后写论文锻炼出来的。就我目前比大多数人强的表达能力来说,我以我母校的荣誉保证,reversed确实比L[::-1]好。

any

在内置函数中,sort、sum、min和max是大家用的比较多的,也比较熟悉的。像any和all这种函数,是大家都知道,并且觉得很简单,但是使用的时候就想不起来的。我们来看一个具体的例子。

我们现在的需求是判断MySQL中的一张表是否存在主键,有主键的情况,如下所示:

    mysql> show index from t;
    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | t     |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    1 row in
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值