来源:https://segmentfault.com/a/1190000003721694
https://segmentfault.com/a/1190000004341701
python tips(1)
给dict设置默认值
这样能设置所有key的默认值为[],包括新添的key
from collections import defaultdict
context = defaultdict(list)
setdefault一次只能设置一个值,但好处是能使用链式语法,但defaultdict
更快一些
context = {}
context.setdefault('name_list', []).append('Fiona')
或者用fromkeys,用法dict.fromkeys(seq[,
value]))
,value
默认是国际惯例的None
name_list = ['kevin', 'robin']
context = {}.fromkeys(name_list, 9)
# {'kevin': 9, 'robin': 9}
context = dict.fromkeys([1, 2], True)
# {1: True, 2: True}
列表去重的快速方法
比用set要快,来自:http://www.peterbe.com/plog/uniqifiers-benchmark
{}.fromkeys(mylist).keys()
列表深复制
a = [3, 2, 1]
b = a[:]
字典深复制
a = {'male':0, 'female': 1}
b = a.copy()
时间转换相关
获取今天的年月日时间(date)
两种代码效果相同
from datetime import datetime
n_date = datetime.now().date()
n_date = datetime.today().date()
date -> datetime
from datetime import datetime
b = datetime.combine(n_date, datetime.min.time())
# datetime.datetime(2015, 9, 8, 0, 0)
datetime -> date
比较简单,直接使用datetime_object.date()
即可
# datetime.datetime(2015, 6, 5, 11, 45, 45, 393548)
a = datetime.datetime()
# datetime.datetime(2016, 6, 5)
b = a.date()
time.struct_time -> datetime
一般time.localtime()
或者用time.striptime()
得到的就是time.struct_time
使用位置参数
structTime = time.localtime()
datetime.datetime(*structTime[:6])
# datetime.datetime(2009, 11, 8, 20, 32, 35)
或者使用datetime.fromtimestamp
,但是要注意此处的时间不能早于1970-01-01
00:00
from time import mktime
from datetime import datetime
dt = datetime.fromtimestamp(mktime(struct))
计算日期之差
from datetime import date
d0 = date(2008, 8, 18)
d1 = date(2008, 9, 26)
delta = d0 - d1
print delta.days
获取milliseconds(13位数字)
import time
from datetime import datetime
time.time() # 1441769033.549239
int(time.time() * 1000) # 1441769033549
# or
def unix_time_milliseconds:
time_gap = datetime.utcnow() - datetime.utcfromtimestamp(0)
return int(time_gap.total_seconds() * 1000) # 1441769033549
使用map作iterator
当将func设置为None时,可起到iterator的作用,结果类似于使用了zip,唯一的区别是map可以按最长的列表扩展。
python2.x中的itertools.zip_longest
可以起到与此处map相同的效果
map(None, xrange(3), xrange(10,12))
# [(0, 10), (1, 11), (2, None)]
zip(xrange(3), xrange(10,12))
# [(0, 10), (1, 11)]
判断奇数
自然是使用位操作最快了
if a & 1:
print 'it is even'
dict删除key
要删除的key数量较多(超多一半)的话,建议重新生成dict
;如果数量较少,在pop
和del
都可以的情况下,del
稍快一些
python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "d1 = d.copy()" "for k in d1.keys():" " if k.startswith('f'):" " del d1[k]"
# 1000000 loops, best of 3: 0.827 usec per loop
python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "d1 = d.copy()" "for k in d1.keys():" " if k.startswith('f'):" " d1.pop(k)"
# 1000000 loops, best of 3: 0.96 usec per loop
python tips(2)
join函数的使用
一般的字符串组合操作都建议使用join
, 字符串操作经常使用的就join
, split
, replace
,
另外还有partition
join
里面可以写成一个列表解析的形式
m = map(str, range(9))
','.join(x for x in m if x != '3')
# 而不是
','.join([x for x in m if x != '3'])
从列表中删除多个相同的元素
用list.remove
是不行的, 只能删除从左到右找到的第一个元素, 后面的不会删除
自认为两种比较好的方式如下
m = ['a', 'b', 'c', 'a']
m = filter(lambda x: x !='a', m)
或者
m[:] = (x for x in m if x != 'a')
随机生成n位字符串
import random
import string
rand_str = "".join([random.choice(string.letters+string.digits) for _ in xrange(n)])
引用类型的问题
函数参数
函数默认参数,只在定义时参数求值了一次,函数的多个调用将使用同一个可变参数
def test(data, x=[]):
x.append(data)
return x
print test(3)
# [3]
print test(4)
# [3, 4]
dict.fromkeys设置默认值的问题
和函数参数问题一样,多个键值对应的value
将调用同一个列表。设置为{}
自然也是一样的结果
>>> a = dict.fromkeys('bc', [])
>>> a['b'].append(6)
>>> a
{'b': [6], 'c': [6]}
多个变量声明
一般会有声明多个空list
和空dict
的需求
将导致多个变量共享同一个[]
或{}
的错误的做法
a = b = []
c = d = {}
正确的方式
a, b = [], []
# for a lot of var
c, d, e, f = [{} for _ in xrange(4)]
其它int
, str
, bool
等没有此问题,可直接写成
a = b = True
del
的时候一次可以删除多个
>>> a = range(3)
>>> del a[2], a[0]
>>> a
[1]
切片操作
可以用-1来反转列表
>>> a = range(7)
>>> a[::-1]
[6, 5, 4, 3, 2, 1, 0]
>>> a[::2]
[0, 2, 4, 6]
用切片删除某一段序列,等同于del a[1:4]
>>> a = [1, 2, 3, 4, 5, 6, 7]
>>> a[1:4] = []
>>> a
[1, 5, 6, 7]
去除偶数索引
>>> a = [0, 1, 2, 3, 4, 5, 6, 7]
>>> del a[::2]
>>> a
[1, 3, 5, 7]
关于省略号
主要用于多维矩阵中,减少定位操作时的复杂度,用得不多,更仔细的说明见这里
>>> class C(object):
... def __getitem__(self, item):
... return item
...
>>> C()[1:2, ..., 3]
(slice(1, 2, None), Ellipsis, 3)
文件操作
一次读取整个文件
使用二进制模式,如rb
模式, 使用r
则只能读取到一部分
with open(path, 'rb') as f:
return f.read()
按行读取
将文件对象看错iterator
with open(path, 'r') as f:
for line in f:
print line