Python中常见的反模式
通过学习这些常见的反模式来改进和简化你的代码,这将为你节省时间和精力。包括好的和坏的做法的例子。
1.不使用with 来打开文件
当你在没有使用with 语句的情况下打开一个文件时,你需要记住在处理完后通过显式调用close() 来关闭文件。即使是显式关闭资源,也有可能在资源真正被释放之前出现异常。这可能导致不一致,或导致文件被破坏。通过with 打开一个文件,实现了上下文管理协议,当执行在with 块之外时,释放资源。
不好的做法:
Python
new_file = open('some-file.txt', 'r')
# do something exciting
new_file.close()
好的做法:
Python
with open('some-file.txt', 'r') as fd:
data = fd.read()
# do something exciting
2.不必要地使用list/dict/set Comprehension
像all,any,enumerate,iter,itertools.cycle 和itertools.accumulate 这样的内置函数可以直接与生成器表达式一起工作。它们不需要理解。
除了它们之外,Python 中的all() 和any() 也支持短路,但是如果使用了理解,这种行为就会消失。这影响了性能。
不好的做法:
Python
...
comma_seperated_names = ','.join([name for name in my_fav_superheroes])
好的做法:
Python
...
comma_seperated_numbers = ','.join(name for name in my_fav_superheroes)
3.生成器的不必要的使用
在调用list,dict 或set 的过程中使用生成器表达式是不必要的,因为这些类型都有相应的理解力。不要在生成器表达式周围使用list/dict/set ,可以把它们写成各自的理解。
不好的做法:
Python
squares = dict((i,i**2) for i in range(1,10))
好的做法:
Python
squares = {i: i**2 for i in range(1,10)}
4.在一个函数调用中返回一个以上的对象类型
在一个函数中拥有不一致的返回类型会使代码变得混乱和复杂,并且可能导致难以解决的错误。如果一个函数应该返回一个给定的类型(如整数常数、列表、元组),但也可以返回其他的东西,那么该函数的调用者将总是需要检查返回的值的类型。建议从一个函数中只返回一种类型的对象。
如果在某些失败的情况下需要返回空的东西,建议引发一个可以被干净地捕获的异常。
不好的做法:
Python
def get_person_age(name):
person = db.get_person(name)
if person:
return person.age # returns an int
# returns None if person not found
好的做法:
Python
def get_person_age(name):
person = db.get_person(name)
if not person:
raise Exception(f'No person found with name {name}')
return person.age # guaranteed to return int every time
5.不使用get() 来从字典中返回默认值
这种反模式影响了代码的可读性。我们经常看到这样的代码:创建一个变量,给它分配一个缺省值,然后检查字典中的某个键。如果这个键存在,那么这个键的值就会被分配给这个变量的值。虽然这样做没有什么错,但是这样做很啰嗦,而且效率很低,因为它查询了两次字典,而使用字典的get() 方法就可以轻松完成。
不好的做法:
Python
currency_map = {'usd': 'US Dollar'}
if 'inr' in currency_map:
indian_currency_name = currency_map['inr']
else:
indian_currency_name = 'undefined'
好的做法:
Python
currency_map = {'usd': 'US Dollar'}
indian_currency_name = currency_map.get('inr', 'undefined')
6.不使用items() 来迭代一个字典
在一个字典上的items 方法返回一个包含键值图元的可迭代文件,它可以在for 循环中被解包。这种方法是习惯性的,因此,推荐使用。
不好的做法:
Python
for code in country_map:
name = country_map[code]
# do something with name
好的做法:
Python
for code, name in country_map.items():
# do something with name
pass
7.不使用字面语法来初始化空的list/dict/tuple
通过调用dict() 来初始化一个空字典,相对来说比使用空字面要慢一些,因为必须在全局范围内查找名称dict ,以防它被反弹。其他两种类型也是如此 -list() 和tuple() 。
不好的做法:
Python
my_evans = list()
# Add something to this empty list
好的做法:
Python
my_evans = []
# Add something to this empty list
8.在生产代码中推送调试器
我们中的大多数人至少都做过一次这样的事情--在调试代码时,可能会发生在发现错误后推送代码,但却忘记删除调试器。这很关键,会影响代码的行为。强烈建议在签到前对代码进行审计,以删除调试器的调用。
使用Python分析器,你可以在代码库中的所有这些反模式在它们落入生产之前就被发现。
编码愉快
经Srijan Saurav许可发表于DZone点击这里查看原文。
DZone贡献者所表达的观点属于他们自己。