我应该让我的Python代码降低容错性以提高可读性吗?
我想让我的代码尽量不出错,但我发现这样写代码花了很多时间,读代码也变得更费劲。
比如,我本来可以这样写:
class TextServer(object):
def __init__(self, text_values):
self.text_values = text_values
# <more code>
# <more methods>
但我更倾向于这样写:
class TextServer(object):
def __init__(self, text_values):
for text_value in text_values:
assert isinstance(text_value, basestring), u'All text_values should be str or unicode.'
assert 2 <= len(text_value), u'All text_values should be at least two characters long.'
self.__text_values = frozenset(text_values) # <They shouldn't change.>
# <more code>
@property
def text_values(self):
# <'text_values' shouldn't be replaced.>
return self.__text_values
# <more methods>
我这样写的风格是不是太过于小心翼翼了?有没有什么办法可以在保持代码不出错的同时,让它更容易读呢?
- 注意 1:我在
<
和>
之间加的注释只是为了让大家更明白。 - 注意 2:我最想防止的“傻瓜”就是未来的我自己。
10 个回答
你的代码有点过于“小心翼翼”(特别是当你只是想保护自己时)。
在Python的圈子里,LBYL(即“先检查再使用”)通常(但并不总是)不太受欢迎。不过,还有一个(通常没有明说的)假设,就是大家都有(良好的)单元测试。
就我个人而言?我觉得代码的可读性非常重要。我的意思是,如果你自己觉得代码难以阅读,那别人会怎么想呢?而且可读性差的代码更容易出现错误。更不用说,这样的代码让你在处理时变得更加困难和耗时(你得花时间去弄清楚代码到底在做什么,因为有太多的LBYL)。
“我的Python编码风格是不是太小心翼翼了?有没有办法在保持代码安全的同时提高可读性?”
你在保护自己免受谁的伤害呢?
是你自己吗?你是不是担心自己忘记了自己写的API?
是同事吗?你是不是担心隔壁的同事会故意通过API传递错误的信息?其实你可以和他们沟通一下,这样能解决很多问题。如果你提供了文档,代码也会简洁很多。
还是说是个完全不负责任的人,他下载了你的代码,却不看API文档,然后用错误的参数调用所有方法?你能给他们提供什么帮助呢?
所谓的“防傻”编码其实并没有太大用处,因为这些情况可以用其他更简单的方法来解决。
如果你是为了防止自己出错,那可能就不太合理了。
如果是为了同事或伙伴,那你应该和他们沟通,确保他们理解API文档。
如果你是为了防范一个假想中的不负责任的程序员,他们想要破坏API,那你也无能为力。毕竟这是Python,他们可以直接查看源代码。既然可以直接修改源代码来搞事情,为什么还要费力去错误使用API呢?
这里有一些关于Python编程风格的好建议,来自这个页面:
与其在代码中提前处理各种特殊情况,不如直接捕捉错误。这个编程风格叫做EAFP(“先请求原谅,而不是请求许可”),和LBYL(“先看再跳”)相对。这样做通常能让代码更易读。例如:
糟糕的写法:
#check whether int conversion will raise an error
if not isinstance(s, str) or not s.isdigit:
return None
elif len(s) > 10: #too many digits for int conversion
return None
else:
return int(str)
更好的写法:
try:
return int(str)
except (TypeError, ValueError, OverflowError): #int conversion failed
return None
(注意,在这个例子中,第二种写法要好得多,因为它能正确处理前面的+和-符号,以及32位机器上2到100亿之间的值。不要在代码中提前考虑所有可能出错的情况:直接尝试一下,并使用合适的错误处理方式。)