我是否应该使我的python代码不那么简单,以提高可读性?

时间:2009-12-26 14:58:19

标签: python coding-style readability

我尝试让我的代码变得傻瓜,但我注意到输入内容需要花费大量时间,而且需要更多时间来阅读代码。

而不是:

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>

我的python编码风格是否偏执?或者有没有办法提高可读性,同时保持万无一失?

  • 注1:我在<>之间添加了评论,仅供澄清。
  • 注意2:我试图阻止滥用我的代码的主要傻瓜是我未来的自我

10 个答案:

答案 0 :(得分:12)

以下是this page对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

(请注意,在这种情况下,第二个版本要好得多,因为它正确处理前导+和 - ,并且值也在200到100亿之间(对于32位机器)。不要通过预期来混淆代码所有可能的失败:只需尝试并使用适当的异常处理。)

答案 1 :(得分:9)

“我的python编码风格是否过于偏执?还是有办法提高可读性,同时保持它的万无一失?”

你是傻瓜谁是保护自己的?

您?您是否担心自己不记得自己编写的API?

同行?您是否担心下一个小隔间中的某个人会积极努力通过API传递错误的内容?您可以与他们交谈以解决此问题。如果您提供文档,它会节省大量代码。

一个完整的反社会人员会下载您的代码,拒绝阅读API文档,然后使用不正确的参数调用所有方法?您可以为他们提供哪些帮助?

“傻瓜式”编码并不是非常有用,因为所有这些场景都更容易以另一种方式解决。

如果你是对自己的傻瓜,也许这不是真的明智。

如果你是一个同事或同伴的傻瓜,你应该 - 或许 - 与他们交谈并确保他们理解API文档。

如果你对一些想要破坏API的假想的反社会程序员进行万无一失,那么你无能为力。这是Python。他们有源头。当他们可以编辑源代码来破坏事物时,为什么他们会努力滥用API呢?

答案 2 :(得分:3)

在Python中使用私有实例属性,然后通过属性公开它是不常见的。只需使用self.text_values

答案 3 :(得分:3)

您的代码太偏执(特别是当您只想保护自己时)。

在Python圈子里,LBYL通常(但并不总是)不赞成。 还有(经常没有说明)假设一个人有(好的)单元测试。

我个人?我认为可读性至关重要。我的意思是,如果你你自己认为它很难读,其他人会怎么想?而不太可读的代码也更容易捕获错误。更不用说让它更难/更耗时(你必须挖掘以找到所有LBYLing中实际所做的的代码)

答案 4 :(得分:2)

如果你试图使你的代码完全万无一失,那么有人会发明一个更好的傻瓜。说真的,一个好的经验法则是防止可能的错误,但不要弄乱你的代码,试着想一想调用者可能会打破你的每一种可能的方式。

答案 5 :(得分:2)

而不是花时间在assert和私有变量,我更喜欢花时间在文档和测试用例中。我更喜欢阅读文档,当我必须阅读代码时,我更喜欢阅读测试。更多的代码成长更为真实。同时,测试为您提供了一个简单的代码和有用的用例。

答案 6 :(得分:2)

我需要对错误检查代码进行检查,以确定它所检查的错误的后果。如果垃圾数据进入我的系统,我发现它之前会有多长时间,确定问题是垃圾数据有多难,修复有多困难?对于像您发布的那样的案例,答案通常“不长”,“不难”,“并不困难”。

但数据会在某个地方持续存在,然后在六周内用作复杂算法的输入?我会检查出来的。

答案 7 :(得分:0)

我认为这不是特定于python的。我坚信合同设计:理想情况下,所有功能都应该有明确的前后条件;不幸的是,大多数语言(埃菲尔是规范的例外)并没有提供特别方便的方法来实现这一点,这有助于澄清和正确之间的明显冲突。

实际上,一种方法是编写'checkValues'方法,以避免混乱__init__。您甚至可以将其压缩为:

def __init__(self, text_values):
   self.text_values = checkValues( text_values )

def checkValues(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.'
    return( frozenset( text_values ) )

另一种方法是使用折叠文本编辑器,可以借助一些评论惯例隐藏/显示前置条件;这对于自动生成文档也很有用。

答案 8 :(得分:0)

将你所有的精力放在参数检查中,并将其转换为编写清晰,简洁的文档字符串。

除非您正在为核反应堆编写代码;在这种情况下,我很感谢你两个都做。

答案 9 :(得分:0)

另一种思考方式是:您只需要捕获可以纠正的错误。如果你正在检查输入只是为了用AssertionError中止,你最好只是允许代码稍后引发相应的异常,这样你就可以正确调试。

这条线特别糟糕,因为它会阻止鸭子输入:

        assert isinstance(text_value, basestring), u'All text_values should be str or unicode.'