假设我有一个函数,我想分析运行时的确切步数:
def function(L):
print ("Hello")
i = 0 # 1 step
while i < len(L): # 3 steps
print (L[i] + 1)
i += 2 # 2 steps
print ("Goodbye")
我想知道打印语句是否算作一个步骤?
假设我有一个函数,我想分析运行时的确切步数:
def function(L):
print ("Hello")
i = 0 # 1 step
while i < len(L): # 3 steps
print (L[i] + 1)
i += 2 # 2 steps
print ("Goodbye")
我想知道打印语句是否算作一个步骤?
在这种情况下,“步骤”不是一个定义明确的术语——正如pswaminathan 指出的那样,通常我们关心的不是精确的数值,而是更广泛意义上的数学行为:随着问题规模变大(在在这种情况下,如果您增加输入的大小L
)执行时间是否保持不变?线性增长?二次方?成指数的?
显式计算步数可能是该分析的一部分——它可能是一种对算法进行直观处理的好方法。但是我们没有一致的方法来确定什么是“步骤”,什么不是。您可能正在查看代码行——但在 Python 中,例如,列表推导式可以在一行中表达一个长而复杂的循环。或者您可以计算 CPU 指令,但是使用一种充满抽象的高级语言,这非常困难。所以你选择一个启发式——在像你的例子这样简单的代码中,“每行代码的每次执行都是一个步骤”是一个不错的规则。在这种情况下,您肯定会计算打印语句。如果您想更深入一点,可以按照tobias_k 的建议查看字节码, 以了解 Python 语法背后的指令是什么样的。
但没有单一的商定规则。你提到它是为了家庭作业;在这种情况下,只有您的讲师知道他们希望您使用什么定义。也就是说,您的问题的简单答案很可能是“是的,打印语句很重要”。
如果您的任务是计算确切的步骤数,那么是的,print
将计为一个步骤。但也请注意,您的第二步print
至少需要三个步骤:列表访问、添加和打印。
事实上,print
(和其他“原子”语句)实际上可能值得很多“步骤”,具体取决于您如何解释步骤,例如 CPU 周期等。这对您的分配来说可能是多余的,但准确地说,它可能是值得一看生成的字节码。尝试这个:
import dis
print dis.dis(function)
这将为您提供函数中或多或少的原子步骤的完整列表,例如,加载函数、将参数传递给该函数、从堆栈中弹出元素等。据此,即使您的第一个print
步骤也值得三个步骤(在 Python 2.6 中):
2 0 LOAD_CONST 1 ('Hello')
3 PRINT_ITEM
4 PRINT_NEWLINE
如何解释:第一个数字 ( 2
) 是行号(即,以下所有说明仅针对该行);中心数字 ( 0
) 是跳转标签(由例如 if 语句和循环使用),后面是实际指令 ( LOAD_CONST
);右列包含这些指令的参数 ( 'Hello'
)。有关更多详细信息,请参阅此答案。