Pythonic 写法总结

Python 这门语言的, 入门容易, 精通难, 难在语法糖吧. Python有很多trick, 可以让代码更优雅,高效,高质量.
  2016年6~8月我周末都是在听一些公开课,在cs212上学了一些更Pythonic的写法:

找出一个列表中元素出现次数最多的元素:

1
2
3
4
5
6
7
a = [1,2,3,4,2,2,3,3,3,1]
# 统计a中每个元素出现的次数
>>> b = {i:a.count(i) for i in set(a) }
>>> b
{1: 1, 2: 2, 3: 1, 4: 1}
# 返回value 最大值的key
>>> max(b, key=b.get)

关于 Super

1,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.__init__()是为了继承父类的init.
2. 如果在子类中需要重新定义self.XXX , 则 super 需要放在最上面
Ps : Python deepcopy 很浪费资源的
## 用字典映射
```Python
remap = {
ord('\n'):'',
ord('\t'):' '
}
line = line.translate(remap)

actions = {
2: print_help,
3: save_help,
}
action = actions.get(argc, usage)
action()
# 用字典映射不同的方法

#常见的Python写法:
###生成器(gernerator), yield, .next()

1
2
3
4
5
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x104feab40>
>>> for n in g:
... print n

迭代器:

1
2
3
4
5
6
7
8
9
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> for ch in 'ABC':
... print ch
...
A
B
C

列表生成式:

1
2
3
4
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

map / reduce / Filter:

1
2
3
4
5
6
>>>map(函数, 可迭代的对象)
>>>reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
def is_odd(n):
return n % 2 == 1
filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])
# 结果: [1, 5, 9, 15]

匿名函数

一些魔法方法

枚举

利用collections.deque 保留有限的历史纪录:

使用 deque(maxlen=N) 构造函数会新建一个固定大小的队列。当新的元素加入并 且这个队列已满的时候,最老的元素会自动被移除掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> q = deque(maxlen=3) 
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q
deque([1, 2, 3], maxlen=3)
>>> q.append(4)
>>> q
deque([2, 3, 4], maxlen=3)
>>> q.append(5)
>>> q
deque([3, 4, 5], maxlen=3)
# 在队列两端插入或删除元素时间复杂度都是 O(1) ,而在列表的开头插入或删除元 素的时间复杂度为 O(N)

如何在循环中获取下标:

1
2
3
for idx, val in enumerate(ints):
print idx, val
# 使用enumerate

如何判断一个对象是否拥有某个属性:

1
2
if hasattr(a, 'property'):
a.property

@staticmethod和@classmethod的区别

is是身份测试,==是相等测试:

1
2
3
4
5
6
>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

如何获取文件扩展名:

1
2
3
4
5
6
>>> import os
>>> fileName, fileExtension = os.path.splitext('/path/to/somefile.ext')
>>> fileName
'/path/to/somefile'
>>> fileExtension
'.ext'

如何获取list中包含某个元素所在的下标:

1
2
>>> [“foo”,“bar”,“baz”].index('bar')
1

浅拷贝深拷贝

  • 对象的赋值是:获得了当前元素的地址元素以及子元素的地址
  • 浅拷贝: 浅拷贝仅仅复制了容器中元素的地址
  • 深拷贝,完全拷贝了一个副本,容器内部元素地址都不一样

总结: 浅拷贝深拷贝的问题还是跟Python的引用机制有关, 说白了, append,pop这些操作, 不更换地址.
而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。
也就是说, 地址里的内存元素不可变, 只能另外申请一个内存.