不使用 pythonic 的循环:

l = [1,2,3]

#Bad
for i in range(0,len(list)):
le = l[i]
print(i,le) #Good
for i,le in enumerate(l):
print(i,le)

函数调用返回一个以上的变量类型

#Bad

def filter_for_foo(l):
r = [e for e in l if e.find("foo") != -1]
if not check_some_critical_condition(r):
return None
return r res = filter_for_foo(["bar","foo","faz"]) if res is not None:
#continue processing
pass #Good def filter_for_foo(l):
r = [e for e in l if e.find("foo") != -1]
if not check_some_critical_condition(r):
raise SomeException("critical condition unmet!")
return r try:
res = filter_for_foo(["bar","foo","faz"])
#continue processing
except SomeException:
#handle exception

循环永不终止


#example:
i = 0
while i < 10:
do_something()
#we forget to increment i

不使用 .iteritems() 遍历 dict 的键/值对.


#Bad d = {'foo' : 1,'bar' : 2} for key in d:
value = d[key]
print("%s = %d" % (key,value)) #Good for key,value in d.iteritems():
print("%s = %d" % (key,value))

不使用 zip() 遍历一对列表


#Bad l1 = [1,2,3]
l2 = [4,5,6] for i in range(l1):
l1v = l1[i]
l2v = l2[i]
print(l1v,l2v) #Good for l1v,l2v in zip(l1,l2):
print(l1v,l2v)

Using "key in list" to check if a key is contained in a list.

This is not an error but inefficient, since the list search is O(n). If possible, a set or dictionary

should be used instead.

Note: Since the conversion of the list to a set is an O(n) operation, it should ideally be done only once when generating the list.


#Bad: l = [1,2,3,4] if 3 in l:
pass #Good s = set(l) if 3 in s:
pass

在循环之后,不使用 'else'.


#Bad found = False l = [1,2,3] for i in l:
if i == 4:
found = True
break if not found:
#not found...
pass #Good for i in l:
if i == 4:
break
else:
#not found...

对于dict,不使用.setdefault()设置初始值


#Bad d = {} if not 'foo' in d:
d['foo'] = [] d['foo'].append('bar') #Good d = {} foo = d.setdefault('foo',[])
foo.append(bar)

对于dict,不使用.get()返回缺省值


#Bad d = {'foo' : 'bar'} foo = 'default'
if 'foo' in d:
foo = d['foo'] #Good foo = d.get('foo','default')

使用map/filter而不是列表解析


#Bad: values = [1,2,3] doubled_values = map(lambda x:x*2,values) #Good doubled_values = [x*2 for x in values] #Bad filtered_values = filter(lambda x:True if x < 2 else False,values) #Good filtered_values = [x for x in values if x < 2]

不使用defaultdict


#Bad d = {} if not 'count' in d:
d['count'] = 0 d['count']+=1 #Good from collections import defaultdict d = defaultdict(lambda :0) d['count']+=1

从一个函数中返回多个值时,不使用命名元组(namedtuple)

命名元组可以用于任何正常元组使用的地方,但可以通过name访问value,而不是索引。这使得代码更详细、更容易阅读。


#Bad def foo():
#....
return -1,"not found" status_code,message = foo() print(status_code,message) #Good from collections import namedtuple def foo():
#...
return_args = namedtuple('return_args',['status_code','message'])
return return_args(-1,"not found") ra = foo() print(ra.status_code,ra.message)

不使用序列的显式解包

支持解包的序列有:list, tuple, dict


#Bad l = [1,"foo","bar"] l0 = l[0]
l1 = l[1]
l2 = l[2] #Good l0,l1,l2 = l

不使用解包一次更新多个值


#Bad x = 1
y = 2 _t = x x = y+2
y = x-4 #Good x = 1
y = 2 x,y = y+2,x-4

不使用'with'打开文件


#Bad f = open("file.txt","r")
content = f.read()
f.close() #Good with open("file.txt","r") as input_file:
content = f.read()

要求许可而不是宽恕


#Bad import os if os.path.exists("file.txt"):
os.unlink("file.txt") #Good import os try:
os.unlink("file.txt")
except OSError:
pass

不使用字典解析


#Bad l = [1,2,3] d = dict([(n,n*2) for n in l]) #Good d = {n : n*2 for n in l}

使用字符串连接,而不是格式化


#Bad n_errors = 10 s = "there were "+str(n_errors)+" errors." #Good s = "there were %d errors." % n_errors

变量名包含类型信息(匈牙利命名)


#Bad intN = 4
strFoo = "bar" #Good n = 4
foo = "bar"

实现java风格的getter和setter方法,而不是使用属性。


#Bad class Foo(object): def __init__(a):
self._a = a def get_a(self):
return a def set_a(self,value):
self._a = value #Good class Foo(object): def __init__(a):
self._a = a @property
def a(self):
return self._a @a.setter
def a(self,value):
self._a = value #Bad def calculate_with_operator(operator, a, b): if operator == '+':
return a+b
elif operator == '-':
return a-b
elif operator == '/':
return a/b
elif operator == '*':
return a*b #Good def calculate_with_operator(operator, a, b): possible_operators = {
'+': lambda a,b: a+b,
'-': lambda a,b: a-b,
'*': lambda a,b: a*b,
'/': lambda a,b: a/b
} return possible_operators[operator](a,b) #Bad class DateUtil:
@staticmethod
def from_weekday_to_string(weekday):
nameds_weekdays = {
0: 'Monday',
5: 'Friday'
} return nameds_weekdays[weekday] #Good def from_weekday_to_string(weekday):
nameds_weekdays = {
0: 'Monday',
5: 'Friday'
} return nameds_weekdays[weekday]

python 反模式的更多相关文章

  1. Python编程中的反模式

    Python是时下最热门的编程语言之一了.简洁而富有表达力的语法,两三行代码往往就能解决十来行C代码才能解决的问题:丰富的标准库和第三方库,大大节约了开发时间,使它成为那些对性能没有严苛要求的开发任务 ...

  2. ORM 是一种讨厌的反模式

    本文由码农网 – 孙腾浩原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! (“Too Long; Didn’t Read.”太长不想看,可以看这段摘要 )ORM是一种讨厌的反模式,违背 ...

  3. 《SQL 反模式》 学习笔记

    第一章 引言 GoF 所著的的<设计模式>,在软件领域引入了"设计模式"(design pattern)的概念. 而后,Andrew Koenig 在 1995 年造了 ...

  4. 重构24-Remove Arrowhead Antipattern(去掉箭头反模式)

    基于c2的wiki条目.Los Techies的Chris Missal同样也些了一篇关于反模式的post.  简单地说,当你使用大量的嵌套条件判断时,形成了箭头型的代码,这就是箭头反模式(arrow ...

  5. Apache Hadoop最佳实践和反模式

    摘要:本文介绍了在Apache Hadoop上运行应用程序的最佳实践,实际上,我们引入了网格模式(Grid Pattern)的概念,它和设计模式类似,它代表运行在网格(Grid)上的应用程序的可复用解 ...

  6. 开发反模式 - SQL注入

    一.目标:编写SQL动态查询 SQL常常和程序代码一起使用.我们通常所说的SQL动态查询,是指将程序中的变量和基本SQL语句拼接成一个完整的查询语句. string sql = SELECT * FR ...

  7. 开发反模式(GUID) - 伪键洁癖

    一.目标:整理数据 有的人有强迫症,他们会为一系列数据的断档而抓狂. 一方面,Id为3这一行确实发生过一些事情,为什么这个查询不返回Id为3的这一行?这条记录数据丢失了吗?那个Column到底是什么? ...

  8. 查询反模式 - 正视NULL值

    一.提出问题 不可避免地,我们都数据库总有一些字段是没有值的.不管是插入一个不完整的行,还是有些列可以合法地拥有一些无效值.SQL 支持一个特殊的空值,就是NULL. 在很多时候,NULL值导致我们的 ...

  9. Python教程(1.2)——Python交互模式

    上一节已经说过,安装完Python,在命令行输入"python"之后,如果成功,会得到类似于下面的窗口: 可以看到,结尾有3个>符号(>>>).>&g ...

随机推荐

  1. 关于touch事件对于性能的影响

    第一次写博客随笔,废话不多说,直接进入正题. 最近一直专注于移动终端的开发,碰到了一个比较棘手的事情,就是touch事件,大家都知道,touch事件有几种,无非就是touchstart,touchmo ...

  2. node.js之excel文件读取

    金天:学习一个新东西,就要持有拥抱的心态,如果固守在自己先前的概念体系,就会有举步维艰的感觉.node.js解析excel, 读取记录. 业务需求,从excel (xlsx, xls)导入数据. 备选 ...

  3. linux 同步IO: sync msync、fsync、fdatasync与 fflush

    最近阅读leveldb源码,作为一个保证可靠性的kv数据库其数据与磁盘的交互可谓是极其关键,其中涉及到了不少内存和磁盘同步的操作和策略.为了加深理解,从网上整理了linux池畔同步IO相关的函数,这里 ...

  4. POI教程之第一讲:创建新工作簿, Sheet 页,创建单元格

    第一讲 Poi 简介 Apache POI 是Apache 软件基金会的开放源码函数库,Poi提供API给java程序对Microsoft Office格式档案读和写的功能. 1.创建新工作簿,并给工 ...

  5. XSLT

    一.简介 XSLT 是一种用于将 XML 文档转换为 XHTML 文档或其他 XML 文档的语言. XSL(eXtensible Stylesheet Language) -- 可扩展标记语言,主要用 ...

  6. linux timezone

    首先需要了解下“UTC时间”与“本地时间”UTC时间:世界协调时间(又称世界标准时间.世界统一时间),在一般精度要求下,它与GMT(Greenwich Mean Time,格林威治标准时间)是一样的, ...

  7. listview中OnItemClick方法各个参数的作用

    OnItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) 1.arg0,arg2 m_listview.setOnI ...

  8. cni 添加网络 流程分析

    cnitool: Add or remove network interfaces from a network namespace cnitool add <net> <netns ...

  9. 项目回顾1-图片上传-form表单还是base64-前端图片压缩

    第一个项目终于上线了,是一个叫亲青筹的公益众筹平台,微信端,电脑端还有后台界面大部分都是我完成的,几个月过来,感觉收获了很多,觉得要总结一下. 首先想到的是图片上传的问题.在通常表单数据都是ajax上 ...

  10. CentOS7.2安装总结

    第一次自己写文章,想想还有点小激动呢.折腾了大半天,终于在一个没用的台式机上面装了个mini版的CentOS7.2.写这篇文章也是做个记载,要是以后再装要注意了. 一.安装过程 采用U盘安装.最初是准 ...