Return 一个完整的表达式,或者 return 它的值存储在一个变量中

Return a complete expresion, or return its value stored in a variable

我正在查看一些代码并找到以下几行:

def get_char_count(tokens):
    return sum(len(t) for t in tokens)


def get_long_words_ratio(tokens, nro_tokens):
    ratio = sum(1 for t in tokens if len(t) > 6) / nro_tokens
    return ratio

如您所见,在第一种情况下,完整的表达式被 returned,而在第二种情况下,表达式首先被计算并存储到一个变量中,然后被 returned .我的问题是,哪种方式更好,更 pythonic 方式?

我不完全确定 Python 如何处理来自函数的 returns。它是通过引用 return 还是直接 return 值?它是否解析表达式和 returns that?总而言之,将表达式的值存储到变量和 return 变量中更好,还是将整个表达式 return 也完全好(效率和 PEP-wise)?

Does it return by reference[?]

实际上是的。当你return一个对象时,函数内部对象的id(即内存地址)与函数外部对象的id相同。它不会制作副本或任何东西。

[...] or does it return the value directly?

如果你说 "is it like the 'pass-by-value' argument passing system of many programming languages, where a copy is made and changes to the new value don't affect the original one? Except for returning values instead of passing them?",那么不,不是那样的。 Python 除非您明确告知,否则不会复制任何内容。

Does it resolve the expression and returns that?

是的。表达式几乎总是立即得到解决。不包括的时间

  • 当您定义了一个函数(但还没有执行它)时,该函数中的表达式将不会被解析,即使 Python 必须 "pass over" 这些行来创建函数对象
  • 当你创建一个 lambda 对象时,(但还没有执行它),...等等等等

In summary, is it better to store an expression's value into a variable and return the variable, or is it also perfectly fine (efficiency, and PEP-wise) to return the expression as a whole?

从函数之外的任何代码的角度来看,这两种方法是完全相同的。你无法区分 "a returned expression" 和 "a returned variable",因为它们具有相同的结果。

你的第二个函数比第一个稍慢,因为它需要为变量名分配 space 并在函数结束时释放它。所以你不妨使用第一种方法,为自己节省一行代码和百万分之一秒的运行时间。

下面是使用这些不同方法的两个函数的字节码分解示例:

def f():
    return 2 + 2

def g():
    x = 2 + 2
    return x

import dis
print("Byte code for f:")
dis.dis(f)

print("Byte code for g:")
dis.dis(g)

结果:

Byte code for f:
  2           0 LOAD_CONST               2 (4)
              2 RETURN_VALUE
Byte code for g:
  5           0 LOAD_CONST               2 (4)
              2 STORE_FAST               0 (x)

  6           4 LOAD_FAST                0 (x)
              6 RETURN_VALUE

请注意,它们都以 RETURN_VALUE 结尾。没有单独的 RETURN_EXPRESSIONRETURN_VARIABLE 代码。

虽然我更喜欢第一种方法(因为它使用的内存更少),但两种表达式在行为上是等效的。

除了与您的 return 陈述保持一致外,PEP8 风格指南并没有真正说明这一点。

Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable).