在功能的顶部“早退”是不错的风格(或更高效)?

时间:2012-03-16 06:42:49

标签: python

对于令人困惑的标题感到抱歉。

我最近在我的项目中开始这样做,我想知道它是否更有效率,以及它是否是一种可怕的练习方式。

以下是数据库界面的示例:

def register(self, user, pw):
    """Register user/pw into the database"""
    if self.isStarted():
        raise Exceptions.Started
    hashed = hashlib.sha512(pw).hexdigest()
    self._db_cur.execute('''INSERT INTO PLAYERS (name, password)
                                    values (?, ?)''', [user, hashed])
    self._db.commit()

我在这里提出异常,但我已经在其他地方做了回复。

我觉得这允许false-cases退出顶部的函数,而不是继续执行函数,看看是否还有更多的代码供它们运行。

我很少在代码中看到这一点:这是一个不好的做法,还是不会像我想象的那样产生任何性能?

为了帮助澄清,我习惯的是:

if (somethingTrue):
    runThis()
    thisToo()
    x = andThis()
    return x
return None

以及我已经开始做的事情,而且我很开心:

if (!somethingTrue):
    return None
runThis()
thisToo()
x = andThis()
return x

后者似乎给人的印象(特别是在超过4行的函数中)代码不是条件的一部分,当它是这样的时候。这也使它看起来更好,同时坚持PEP-8,所以我真的对它有所了解。

我有一种感觉,这打破了一些非常神圣的东西。这是好的还是亵渎神灵?

2 个答案:

答案 0 :(得分:5)

问题的一部分是关于风格和最佳实践 - 因此恕我直言不是'正确'的方式。

在我看来,嵌套版本(没有直接返回)来自'历史'编程语言,如'C',其中整个清理在正确的地方完成一次。人工示例仅显示要点:

int f() {
   int result = 1;
   char * buffer = (char *)malloc(77);
   if(buffer!=NULL) {
      int const fd = open("/tmp/data.log", O_RDONLY);
      if(fd!=-1) {
         ssize_t const read_cnt = read(fd, buffer, 77);
         if(read_cnt!=77) {
            /* Do something: was not possible to read 77 bytes. */
            result = 0;
         }
         close(fd);
      }
      free(buffer);
   }
   return result;
}

从其他行返回到最后一行是不正确的 - 因为那时可能会有资源泄漏。

当只使用在析构函数中完全销毁的对象时 - 或者当不需要清理资源时(因为没有分配),我更喜欢'短'路径返回。这使得事情变得更加清晰:如果函数的前提条件不满足,则无法“真正”执行函数体。另外:你不需要那么多的缩进,它更容易阅读。

表现:我做了一些测试;我无法衡量两种方式之间的差异。恕我直言,如果您需要调整此级别的性能,您可能需要考虑选择其他编程语言。 ; - )

答案 1 :(得分:4)

如果您必须进行检查(为了正确),那么我认为在顶部进行检查是个好主意。

在某些情况下,您可以选择(1)进行检查以避免不必要的工作,或者(2)只是跳过检查并始终进行工作。在这种情况下,你可以考虑跳过支票,如果你认为不做工作的情况会非常罕见,以至于额外支票的费用会比不时做不必要的工作花费更多(如果你真的想确定)。然后,可能不清楚是哪种情况;然后我会说一个简单的if语句非常便宜(假设支票本身并不昂贵),所以只需要检查并且不要太担心,除非你看到性能问题。您可以随时进行分析。

修改:根据您的进一步示例,您可能会想到一个不同的问题。关于这个问题,我会说你通常应该先用最短的代码放一个案例,所以你没有像

这样的东西。
if positive_case:
  lots of stuff
  lots more stuff
  ...
else:
  whatever this corresponds to is now off the screen

您的技术也是避免过多嵌套的常用方法。退出if,然后省略else,就可以展平

if error:
  raise exception
else:
  do more stuff
  if error:
    ...

if error:
  raise exception

do more stuff
if error:
  ...

我想你提到的是,PEP-8实际上提到并推荐了这种技术。我不确定你为什么觉得这可能是亵渎神灵的。许多事情只是个人偏好,无论是利弊还是利弊,你都有权对这些权衡做出自己的看法。