Python 高效编程技能点

作者: 刀背藏身 | 来源:发表于2015-10-28 21:46 被阅读753次

    Python 高效编程小技巧

    个人博客:临风|刀背藏身
    Python 一直被我拿来写算法题,小程序,因为他使用起来太方便了,各种niubi闪闪的技能点也在写算法的过程中逐渐被挖掘到,感谢万能的谷哥度娘SOF以及各大博客网站,在这里整理一二。

    几句废话:

    因为我是懒癌晚期,最不喜欢在文章里发图片,因为Mweb写作或者是马克飞象写作,可以直接拖图进来,但是上传博客的话,就需要考虑是使用服务器上的媒体库,还是放七牛,放七牛上还得用它的命令行工具,或者是Web端操作,想想都好麻烦。所以,本地一直存放着几篇写完的文章楞是没有上传(一篇探索红黑树,一篇是设计模式C++版半完全指南,一篇是Linux的小文章),就是因为往里边塞了太多图片的原因。所以以后写文,尽量控制图片 <= 3。

    下面进入密集式正题,过于炫技的部分被我去掉了,因为我看过之后只是碎了膝盖,然而并不常用。因为自己很少做整理,现在知道整理的强大之处了,所以以后也会注意相关知识的整理。以下方法的适用场景我也就不用多说了,因为都是最最常见的场景:

    1. 拆箱(这个方法比较常见,非常高效)

    变量声明利用拆箱这种方式,非常高效,这也算是Python 里最常用的技巧了,也是我最开始使用 Python 时感觉非常惊奇的功能。

    >>> a, b, c = 1, 2, 3
    >>> a, b, c
    (1, 2, 3)
    >>> a, b, c = [1, 2, 3]
    >>> a, b, c
    (1, 2, 3)
    >>> a, b, c = (2 * i + 1 for i in range(3))
    >>> a, b, c
    (1, 3, 5)
    >>> a, (b, c), d = [1, (2, 3), 4]
    >>> a, b, c, d
    1, 2, 3, 4
    

    拆箱也可用于变量交换

    >>> a, b = 1, 2
    >>> a, b = b, a
    >>> a, b
    (2,1)
    

    2. 指定步长的切割

    刚开始接触Python 的时候,被Python 深拷贝的方式逗乐了,写Python 你可以利用想象力写代码。深拷贝利用的就是这个指定步长的切割。

    >>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    >>> a[::2]
    [0, 2, 4, 6, 8, 10]
    >>> a[2:8:2]
    [2, 4, 6]
    # 下边这个实现深拷贝
    >>> print a[::1]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    # 逆序拷贝
    >>> print a[::-1]
    [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    # 你还可以给切割的部分赋值,也可以借此插入数组
    >>> a = [1, 2, 3, 4, 5]
    >>> a[2:3] = [0, 0]
    >>> a
    [1, 2, 0, 0, 4, 5]
    >>> a[1:1] = [8, 9]
    >>> a
    [1, 8, 9, 2, 0, 0, 4, 5]
    # 还有命名列表切割方式
    >>> a = [0, 1, 2, 3, 4, 5]
    >>> last_three = slice(-3, None)
    >>> last_three
    slice(-3, None, None)
    >>> a[last_three]
    [3, 4, 5]
    

    3. 压缩器zip

    zip 这个也是靠想象力实现各种各样的功能。

    1. 列表 or 迭代器的压缩与解压缩
    >>> a = [1, 2, 3]
    >>> b = ['a', 'b', 'c']
    >>> z = zip(a, b)
    >>> z
    [(1, 'a'), (2, 'b'), (3, 'c')]
    >>> zip(*z)
    [(1, 2, 3), ('a', 'b', 'c')]
    
    1. 列表相邻元素压缩器
    >>> a = [1, 2, 3, 4, 5, 6]
    >>> zip(*([iter(a)] * 2))
    [(1, 2), (3, 4), (5, 6)]
    
    >>> group_adjacent = lambda a, k: zip(*([iter(a)] * k))
    >>> group_adjacent(a, 3)
    [(1, 2, 3), (4, 5, 6)]
    >>> group_adjacent(a, 2)
    [(1, 2), (3, 4), (5, 6)]
    >>> group_adjacent(a, 1)
    [(1,), (2,), (3,), (4,), (5,), (6,)]
    
    >>> zip(a[::2], a[1::2])
    [(1, 2), (3, 4), (5, 6)]
    
    >>> zip(a[::3], a[1::3], a[2::3])
    [(1, 2, 3), (4, 5, 6)]
    
    >>> group_adjacent = lambda a, k: zip(*(a[i::k] for i in range(k)))
    >>> group_adjacent(a, 3)
    [(1, 2, 3), (4, 5, 6)]
    >>> group_adjacent(a, 2)
    [(1, 2), (3, 4), (5, 6)]
    >>> group_adjacent(a, 1)
    [(1,), (2,), (3,), (4,), (5,), (6,)]
    
    1. 用压缩器翻转字典
    >>> m = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    >>> m.items()
    [('a', 1), ('c', 3), ('b', 2), ('d', 4)]
    >>> zip(m.values(), m.keys())
    [(1, 'a'), (3, 'c'), (2, 'b'), (4, 'd')]
    >>> mi = dict(zip(m.values(), m.keys()))
    >>> mi
    {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
    

    4. 列表展开

    列表展开的方式五花八门,动用大脑可以创造各种各样的方法,最便于理解的是以下两种:

    >>> a = [[1, 2], [3, 4], [5, 6]]
    >>> sum(a, [])
    [1, 2, 3, 4, 5, 6]
    >>> [x for l in a for x in l]
    [1, 2, 3, 4, 5, 6]
    

    5. 生成器表达式

    >>> g = (x ** 2 for x in xrange(10))
    >>> next(g)
    0
    >>> next(g)
    1
    >>> next(g)
    4
    >>> sum(x ** 3 for x in xrange(10))
    2025
    >>> sum(x ** 3 for x in xrange(10) if x % 3 == 1)
    408
    

    6. 字典推导和集合推导

    一上来我打成了推倒是什么心理,相信在平时推导过列表,他还有更多的应用方式。

    # 这个是最常见的推导
    >>> list1 = [1,2,3,4,5]
    >>> list2 = [x + 1 for x in list1]
    >>> list2
    [2, 3, 4, 5, 6]
    # 我们可以用语法来创建集合和字典表,开开脑洞
    >>> some_list = [1, 2, 3, 4, 5, 2, 5, 1, 4, 8]
    >>> even_set = { x for x in some_list if x % 2 == 0 }
    >>> even_set
    set([8, 2, 4])
    # 其实,我们有更简单的方式创建一个集合:
    >>> setlist = {1,2,3,4,5,2,3,4}
    >>> setlist
    set([1,2,3,4,5])
    # 创建字典表
    >>> d = { x: x % 2 == 0 for x in range(1, 11) }
    >>> d
    {1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False, 10: True}
    # 利用这个脑洞,你还可以用字典推导翻转字典
    >>> m = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    >>> m
    {'d': 4, 'a': 1, 'b': 2, 'c': 3}
    >>> {v: k for k, v in m.items()}
    {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
    

    另外,刚刚提到了,直接省略set 方式的创建集合,它还有一些在这基础之上更犀利的应用。

    >>> A = {1, 2, 3, 3}
    >>> A
    set([1, 2, 3])
    >>> B = {3, 4, 5, 6, 7}
    >>> B
    set([3, 4, 5, 6, 7])
    >>> A | B
    set([1, 2, 3, 4, 5, 6, 7])
    >>> A & B
    set([3])
    >>> A - B
    set([1, 2])
    >>> B - A
    set([4, 5, 6, 7])
    >>> A ^ B
    set([1, 2, 4, 5, 6, 7])
    >>> (A ^ B) == ((A - B) | (B - A))
    True
    

    7. Counter 计数器

    对于我们来说,数一个东西,是非常常用的,然而这件事又不是程序员喜欢做的事情,我们用 counter 来完成这个操作。他在我们python 内置的库里。

    >>> from collections import Counter
    >>> c = Counter('hello world')
    
    >>> c
    Counter({'l': 3, 'o': 2, ' ': 1, 'e': 1, 'd': 1, 'h': 1, 'r': 1, 'w': 1})
    
    >>> c.most_common(2)
    [('l', 3), ('o', 2)]
    

    8. 双端队列

    我们都知道,队列和栈实际上就是对在双端队列的基础上实现的,python可以直接操作双端队列。当然也在内置的库 collections 里。

    >>> Q = collections.deque()
    >>> Q.append(1)
    >>> Q.appendleft(2)
    >>> Q.extend([3, 4])
    >>> Q.extendleft([5, 6])
    >>> Q
    deque([6, 5, 2, 1, 3, 4])
    >>> Q.pop()
    4
    >>> Q.popleft()
    6
    >>> Q
    deque([5, 2, 1, 3])
    >>> Q.rotate(3)
    >>> Q
    deque([2, 1, 3, 5])
    >>> Q.rotate(-3)
    >>> Q
    deque([5, 2, 1, 3])
    

    同时,我们还可以在括号里添加 maxlen 来限制双端队列的最大长度。last_three = collections.deque(maxlen=3)

    9. 默认词典

    一般情况下,空词典它就是空的,但是我们利用 collections 里的函数,可以实现默认的字典。

    >>> m = dict()
    >>> m['a']
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 'a'
    # 你可以在括号里添加各种条件
    >>> m = collections.defaultdict(int)
    >>> m['a']
    0
    >>> m['b']
    0
    >>> m = collections.defaultdict(str)
    >>> m['a']
    ''
    >>> m['b'] += 'a'
    >>> m['b']
    'a'
    >>> m = collections.defaultdict(lambda: '[default value]')
    >>> m['a']
    '[default value]'
    >>> m['b']
    '[default value]'
    

    10. 利用json库打印出漂亮的JSON串

    这个方法就是为了让让人面对眼花缭乱的JSON串,能够打印出一个漂亮的可读的格式,对于在控制台交互编程,或者是做日志是,还是非常有用的。另外,也可以注意一下pprint 这个模块。

    import json
    data = {"status": "OK", "count": 2, "results": [{"age": 27, "name": "Oz", "lactose_intolerant": true}, {"age": 29, "name": "Joe", "lactose_intolerant": false}]}
    >>> print(json.dumps(data))  # No indention
    {"status": "OK", "count": 2, "results": [{"age": 27, "name": "Oz", "lactose_intolerant": true}, {"age": 29, "name": "Joe", "lactose_intolerant": false}]}
    
    >>> print(json.dumps(data, indent=2)) {
      "status": "OK",
      "count": 2,
      "results": [
    
        {
          "age": 27,
          "name": "Oz",
    
          "lactose_intolerant": true
        },
        {
          "age": 29,
    
          "name": "Joe",
          "lactose_intolerant": false
        }
      ]
    
    }
    

    11. 最大和最小的几个列表元素

    这个经常用到啊,少年们。

    import random, heapq
    a = [random.randint(0, 100) for __ in xrange(100)]
    b = heapq.nsmallest(5, a)
    c = heapq.nlargest(5, a)
    print b,c
    [1, 2, 3, 5, 7] [100, 100, 100, 99, 98]
    

    12. 一些更贴近大脑的写法,和一些掉了下巴的代码段

    有一些语句,写出来你就能读懂,就像读一篇文章一样。有时候,其他语言用了超长的代码写出来的程序,python只需要几行,甚至是,1行。

    1. 数值比较
    x = 2
    if 3 > x > 1:
       print x
    >>> 2
    if 1 < x > 0:
       print x
    >>> 2
    
    1. 有这么一个算法题,打印数字1到100,3的倍数打印“Fizz”来替换这个数,5的倍数打印“Buzz”,对于既是3的倍数又是5的倍数的数字打印“FizzBuzz”。对此,我们只使用一行代码,搞定它.
    for x in range(1, 101):print"fizz"[x % 3*4::]+"buzz"[x % 5*4::]or x
    

    13. 一个超小型的Web服务

    我们在两台机器或者服务器之间做一些简单的基础的RPC之类的交互,我们就可以用到python 这个神奇的模块。
    服务器:

    from SimpleXMLRPCServer import SimpleXMLRPCServer
    
    def file_reader(file_name):
    
        with open(file_name, 'r') as f:
            return f.read()
    
    server = SimpleXMLRPCServer(('localhost', 8000))
    server.register_introspection_functions()
    
    server.register_function(file_reader)
    
    server.serve_forever()
    

    客户端:

    import xmlrpclib
    proxy = xmlrpclib.ServerProxy('http://localhost:8000/')
    
    proxy.file_reader('/tmp/secret.txt')
    

    这样就得到了一个远程文件读取工具,超小型,没有外部依赖,当然没有任何安全可言,仅作家里使用,当然我现在还没用过这个。


    人生苦短,我用Python。

    ps. 似乎不说一句这个名言,就不像是在写Python一样。当然了,我还是要滚回去好好地学C++。

    相关文章

      网友评论

      本文标题:Python 高效编程技能点

      本文链接:https://www.haomeiwen.com/subject/kmzxhttx.html