Python 高效编程技能点
admin
2023-07-30 20:44:33
0

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\')]
  2. 列表相邻元素压缩器
>>> 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 \"\", line 1, in 
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++。

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
Prometheus+Graf... 一,Prometheus概述 1,什么是Prometheus?Prometheus是最初在Sound...
python绘图库Matplo... 本文简单介绍了Python绘图库Matplotlib的安装,简介如下: matplotlib是pyt...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...