Python开发的一些技巧

1.列表去重最佳的方法:

a = [1,3,4,5,5,5,6,6,7,7,0]
a = list(set(a))

2.使用and-or操作符

a > 5 and ”hello” or a > 3 and ”middle” or ”small”

等同于:

if a > 5:
    return ”hello”
elif a > 3:
    return ”middle”
else:
    return ”small”

3.如何在命令行下输出整齐的文字

python {0:20s}\t{1:d}.format(“name”, ”age”)

4.关于列表推导
何时使用列表推导?当你直觉的考虑改变某列表,而不是新建列表的时候。
列表推导会产生一个全新的列表,而不是修改现有列表。如果需要修改现有列表,则需要对整个列表的切片赋值。

# 以下两种方式得到的结果是一样的,区别在于:
lis = [1,3,4,103,200,400]
# 给一个“整个列表的切片”赋值的同时,修改了该列表对位的数据。
lis[:] = [min(x, 100) for x in lis] 
#给lis重新赋值,重新绑定。
lis = [min(x, 100) for x in lis]

# 注:min函数和max函数可以对数列求最小值或者最大值,参数可以是n个数字,也可以是一个序列
m1 = min(1,2,3,4,5)
m2 = max([0,3,4,6,73,5])

5.如果列表或字典中某元素存在则返回
如果访问列表中不存在的索引的时候,会抛出异常,列表没有类似字典的get方法。
列表的索引规则:有效索引只能在大于等于-len(L)且小于len(L)的这个区间中。

# 最佳方法:
def list_get(l, i, v=None):
    if -len(l) <= i < len(l): return l[i]
    else: return v
# 如果在传进去的索引绝大多数是无效索引的话,上面的方法比这个方法快4倍:
def list_get(l, i, v=None):
    try: return l[i]
    except IndexError: return v
# 如果是字典的情况,参见如下:
a = {'a':'aaa', 'b':'bbb’}
print a['c’] # 将引发一个KeyError的异常
print a.get('c’) # 返回None
print a.get('c’,’hello') # 返回hello,如果None不是你的期望值,可以自定义返回内容

print a.pop('c’) # 将引发一个KeyError的异常

print a.pop('c’, None) # 返回None

key正确的情况下pop和get的返回值一样,pop会同时删除该条目。

6.循环访问序列中的元素和索引
Python最基本的数据结构序列(sequence)主要包括列表,元组,字符串,Unicode字符串,buffer对象和xrange对象。
当循环访问一个序列,需要每一步都知道已经访问到的索引,可以使用enumerate内建函数

# 最佳实践:
for index, item in enumerate(seq):
    if item > 23:
        seq[index] = 23
# 比下面的方法更快:
for index in range(len(seq)):
    if seq[index] > 23:
        seq[index] = 23

7.创建多维列表时注意共享引用的问题

# 需要创建一个5 X 10全为0的阵列
a = [[0] * 3] * 3
[[0,0,0],[0,0,0],[0,0,0]]
a[0][0] = 'a'
[['a’,0,0],['a’,0,0],['a’,0,0]]

这个bug经常会困扰很多人,关键在于[0]*3生成列的时候,有无引用被复制完全不重要,因为被引用的是数字,而数字是不可改变的。而我们创建行的时候,其实是对一个列表的引用,因此其实a包含了3个对列表的引用,这样当第一个子项的第一个子项被改变时,其他的也都改变了。

# 这样是可以避免的,但是不够易读和优雅:
a = [[0] * 3 for row in range(3)]
# 最佳实践:
a = [[0 for col in range(3)] for row in range(3)]

8.在阵列中完成对列的删除和排序
有阵列 lis = [[1,2,3,4],[5,6,7,8],[9,10,11,12]],需要删除其中的第二列,第三和第四列互换位置。
使用一个简单的列表推导来完成任务。

# 最佳实践:
newlis = [[row[x] for x in (0, 3, 2)] for row in lis]

9.阵列变换

# 有一个列表的列表,需要将行换成列,列换成行
arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
# 最佳实践:
newarr = [r[col] for r in arr] for col in range(len(arr[0]))]

10.给字典增加一个条目
给定一个字典d,当k是有效键时,可以直接使用d[k],如果k不是有效键,则给字典增加一个新条目d[k]
如果字典的值是列表,setdefault方法非常有用,经典应用:

somedict.setdefault(somekey, []).append(somevalue)

比如:我们正在创建一个由单词到页数的映射,字典将把每个单词映射到这个词出现国的页的页码构成的列表。

def addword(theIndex, word, pagenumber):
    theIndex.setdefault(word, []).append(page number)

对于不可变值,setdefault没那么有用,如果想对单词计数,最好使用:

gettheIndex[word] = theIndex.get(word, 0) + 1

11.获取字典的一个子集
有一个巨大的字典,给定一个特定的键的集合,创建一个包含这个键集合及其对应值的新字典。

# 我原来是这么做的,真是弱到爆了:
d = {'a':'aa', 'b':'bb', 'c':'cc'}
keys = ('a', 'b')
news = {}
for key, value in d.items():
    if key in keys:
        news[key] = value
print news
# 如果不想改动原字典:
def sub_dict(d, keys, default=None):
    return dict([(k, d.get(k, default)) for k in keys])
# 如果从原字典中删除那些符合条件的条目:
def sub_dict_remove(d, keys, default=None):
    return dict([(k, d.pop(k, default)) for k in keys])
d = {'a':'aa', 'b':'bb', 'c':'cc’}
print sub_dict(d, (’a’,’b'))
print sub_dict_remove(d, (’a’,’b’))

12.反转字典
给定一个字典,要求反转字典,将各个值反隐射到键上。通常值不能重复。

# 列表推导式:
def invert_dict(d):
    return dict([(v, k) for k, v in d.iteritems()])

# 对于比较大的字典,可以用标准库itertools则更快一些
def invert_dict_fast(d):
    return dict(izip(d.itervalues(), d.iterkeys()))

13.字典的一键多值

# 正常情况下可以将一个键映射到一个list
d1 = {}
d1 = d1.setdefault(key, []).append(value)
# 或者一个dict上,自然的消灭了值重复的可能
d2 = {}
d2 = d2.setdefault(key, {})[value] = 1
# 等价于
d3 = {}
d3 = d3.setdefault(key, set()).add(value)

14.字典的交集与并集

并集:
union = dict(a, **b)
交集:
inter = dict.fromkeys([x for x in a if x in b])

在for子句中应该用较短的那个字典,在if子句中用较长的字典会有助于速度的提升。
另外,可以使用set来操作交集并集。

标签: python基础

已有 3 条评论

  1. 丁磊 丁磊

  2. 丁磊 丁磊
  3. 马化腾 马化腾

    开公司

添加新评论