写在前面的话
从08年接触Python到现在,断断续续地使用,到如今Python已经成为日常事物处理、科研实验,甚至工程项目的主力语言,主要因为其敏捷性和快速实现的能力。虽然看了一些Python的教程,除了当初那本《Python核心编程》被反复翻看之外,其余还没看到很能让自己Python水平提高的书,虽然也掌握了一些比较Pythonic的方法,但总觉得离真正的深入理解和运用还很远,就像一直属于业余选手,算不上专业队伍那般。直到最近在看《编写高质量代码——改善Python程序的91个建议》和《Python开发实战》,开始有点眼前一亮的感觉,所以,趁此机会,在读书学习的过程中把一些有意思的Pythonic Code做个记录,也方便自己以后查阅。
代码风格与规范
1. 包和模块的命名采用小写、单数形式,而且短小;
2. 包通常仅作为命名空间,如只包含空的__init__.py文件;
参数变量操作
1. 三元操作
1 x=0 2 y=1 3 print x if x>y else y 4 5 #等价于 6 if x>y: 7 print x 8 else: 9 print y
2. 将常量集中到一个文件中
1 # const.py 2 class _const: 3 class ConstError(TypeError): pass 4 class ConstCaseError(ConstError): pass 5 6 def __setattr__(self, name, value): 7 if self.__dict__.has_key(name): 8 raise self.ConstError, "Can't Change const %s." % name 9 if not name.isupper(): 10 raise self.ConstCaseError, \ 11 'const name "%s" is not all uppercase' % name 12 self.__dict__[name] = value 13 14 import sys 15 sys.modules[__name__] = _const() 16 17 # 存放常量的文件 constant.py 18 import const 19 20 const.MY_CONSTANT = 1
3. 枚举类型
使用第三方模块flufl.enum,注:flufl不支持枚举元素比较
1 from flufl.num import Enum 2 #方法一:通过继承的方式实现 3 class Seasons(Enum): 4 Spring = "Spring" 5 Summer = 2 6 Autumn = 3 7 Winter = 4 8 #方法二:直接初始化为Enum类的实例 9 Seasons = Enum('Seasons', 'Spring Summer Autumn Winter') 10 11 #使用枚举值 12 #方法一:得到枚举项的名称 13 print [member for member in Seasons.__members__] 14 #方法二:得到枚举项的值 15 print Seasons.Summer.value
4. 类型检查
使用isinstance(object, classinfo)
5.字符串操作
a. 格式化字符串
1 #在参数比较多的情况下,这样写使得格式化的字符串比较清晰,尤其当参数以dict传递时 2 print 'hello %(name)s' % {'name': 'Tom'} 3 4 #使用str.format()也可以使字符串格式化变得清晰 5 print '%(name)s is %(age)d years old.' % {'name': 'Tom', 'age': 12}
b. 格式化字符串使用format(),更为灵活
weather = [("Monday", "rain"), ("Tuestday", "sunny")] formatter = "Weather of '{0[0]}' is '{0[1]}'".format for item in map(formatter, weather): print item
6. 判断数值=或!=时,尽量使用整型数,浮点数可能由于精度不一,导致无法获得精确一致使判断条件得以满足。
7. 在不可信的计算环境中,尽量避免使用eval(),使用ast.literal_eval代替。
8. 将对象转换成字符串表示,有repre()和str()两种方法:
str()一般是将数值转成字符串。
repr()是将一个对象转成字符串显示,注意只是显示用,有些对象转成字符串没有直接的意思。如list,dict使用str()是无效的,但使用repr可以,这是为了看它们都有哪些值,为了显示之用。
9. 函数传参既不是传值也不是传引用,准确的说法是传对象或者说传对象的引用。对可变对象的修改在函数外部以及内部都可见,调用者和被调用者之间共享这个对象,而对于不可变对象,由于并不能真正被修改,因此,修改往往是通过生成一个新的对象然后赋值实现。(书p75)
列表解析
语法: [expr for iter_item in iterable if cond_expr]
1. 多重迭代,例如两个集合的笛卡尔乘积:
>>> [(a, b) for a in ['a', 1, '1', 'b'] for b in ['1', 2, '2', 'b'] if a!=b] [('a', '1'), ('a', 2), ('a', '2'), ('a', 'b'), (1, '1'), (1, 2), (1, '2'), (1, 'b'), ('1', 2), ('1', '2'), ('1', 'b'), ('b', '1'), ('b', 2), ('b', '2')]
排序
sorted()作用于任意可迭代的对象,list.sort()一般作用于列表,sorted()不改变原有序列对象,返回一个新的对象,而sort()直接改变原有列表。
1. 多键值排序
#这里有两个同为ann,但年龄分别为2和3的小孩 >>> person = [{'name':'joe', 'age':2},{'name':'ann','age':3},{'name':'ben','age':5},{'name':'ann','age':2}] #同时考虑name和age两个键值的排序 >>> sorted(person, key=lambda x: (x['name'],-x['age'])) [{'age': 3, 'name': 'ann'}, {'age': 2, 'name': 'ann'}, {'age': 5, 'name': 'ben'}, {'age': 2, 'name': 'joe'}] #注意这里的键值顺序 >>> sorted(person, key=lambda x: (x['age'],x['name'])) [{'age': 2, 'name': 'ann'}, {'age': 2, 'name': 'joe'}, {'age': 3, 'name': 'ann'}, {'age': 5, 'name': 'ben'}] #另外一种排序方法 >>> from operator import itemgetter >>> sorted(person, key=itemgetter('name','age')) [{'age': 2, 'name': 'ann'}, {'age': 3, 'name': 'ann'}, {'age': 5, 'name': 'ben'}, {'age': 2, 'name': 'joe'}]
2. 字典中混合list排序
>>> mydict = {'Li':[1,'b'], ... 'zhang':[3,'e'], ... 'Wang':[2,'a']} >>> sorted(mydict.iteritems(), key=lambda (k,v): itemgetter(1)(v)) [('Wang', [2, 'a']), ('Li', [1, 'b']), ('zhang', [3, 'e'])] >>> sorted(mydict.iteritems(), key=lambda (k,v): itemgetter(0)(v)) [('Li', [1, 'b']), ('Wang', [2, 'a']), ('zhang', [3, 'e'])]
3. 多维list排序
>>> results = [['ann',10,'b'],['ben',9,'a'],['aris',9,'c']] >>> sorted(results, key=itemgetter(2,1)) [['ben', 9, 'a'], ['ann', 10, 'b'], ['aris', 9, 'c']] >>> sorted(results, key=itemgetter(1,2)) [['ben', 9, 'a'], ['aris', 9, 'c'], ['ann', 10, 'b']] >>> sorted(results, key=itemgetter(0,1)) [['ann', 10, 'b'], ['aris', 9, 'c'], ['ben', 9, 'a']] >>> sorted(results, key=itemgetter(0)) [['ann', 10, 'b'], ['aris', 9, 'c'], ['ben', 9, 'a']]