Python 检测一个方法是否是递归的而不调用它?
这听起来可能是一件愚蠢的事情。上下文是测试驱动的开发:我有一种方法,它涉及到通过树的节点进行下一步操作,为了开发这个函数,我经历了:Python 检测一个方法是否是递归的而不调用它?,python,unit-testing,recursion,inspect,Python,Unit Testing,Recursion,Inspect,这听起来可能是一件愚蠢的事情。上下文是测试驱动的开发:我有一种方法,它涉及到通过树的节点进行下一步操作,为了开发这个函数,我经历了: “查看子节点”“如果子节点有子节点,则查看孙子节点”“如果孙子节点有子节点,则查看曾孙节点”。。。等等 因此,您必须用递归方法替换此代码。如果您使用的是TDD,那么您希望编写一条断言语句,如果您的方法不是递归的,则该语句将失败。对于非TDD的人来说,这可能听起来很愚蠢,但有一点是,树通常涉及相当多的递归功能,因此跳过这种测试步骤实际上感觉“不好” 我想知道insp
“查看子节点”
“如果子节点有子节点,则查看孙子节点”
“如果孙子节点有子节点,则查看曾孙节点”。。。等等 因此,您必须用递归方法替换此代码。如果您使用的是TDD,那么您希望编写一条断言语句,如果您的方法不是递归的,则该语句将失败。对于非TDD的人来说,这可能听起来很愚蠢,但有一点是,树通常涉及相当多的递归功能,因此跳过这种测试步骤实际上感觉“不好”
我想知道inspect模块是否有我需要的。。。但我在挣扎。在我看来,在理想的世界中,您可能希望检测这种递归性,而不必实际调用该方法。您无法可靠地检查函数是否使用递归,否 一个简单的递归函数将查找具有相同名称的全局函数并调用它,因此您必须查看函数字节码或将字节码解析为AST,然后尝试查找对具有相同名称的全局对象的调用。但是,如果正在使用某个方法或函数有别名,您将面临更困难的检测任务 此外,您通常测试被测试对象的功能,而不是具体实现。测试期望的结果,而不是如何产生这些结果 也许您希望避免递归,因为可能会耗尽堆栈。在这种情况下,您需要测试是否会耗尽堆栈
将堆栈深度设置为一个较小的数字(使用),创建一个比堆栈具有更多级别的树,然后尝试解析它。如果抛出
运行时错误
异常,则说明您使用的是递归或另一种过度依赖Python调用堆栈的方法。即使在执行“TDD”时,检查方法是否是递归的也不是一个好主意。想一想,即使你能发现这个方法是递归的,但递归代码可能有一千种错误
相反,在进行TDD时,对您将要处理的数据集提出一个小而好的表示形式,并编写案例以检查您正在编写的函数是否能够很好地处理它们
让我们考虑递归函数的一个例子来解析和查找树节点的总和。
def total(tree):
if tree == None: return 0
return total(tree.left) + total(tree.right) + tree.cargo
这里有一些测试数据案例我会考虑测试<代码>函数而不是测试<代码>实现<代码>函数:
阳性测试以确保总数正确操作,递归与否。这是单元测试的目的。测试功能,而不是实现的详细信息。
一旦您确信您的测试是健壮的,并且任何通过这些测试的函数都是好函数,那么该函数的实现方式就无关紧要了。它可能是递归的,也可能不是递归的,但是在编写单元测试时,您不应该在意 当某人使用堆栈实现(正确的)树遍历函数时,测试结果会发生什么变化?你确定这就是你想要测试的吗?你通常测试功能,而不是具体的实现。你为什么关心它是否是递归实现的?@goncalopp抱歉,我真的不明白你的意思…@jonsharpe:根据我尝试采用的TDD方法/理念,应用程序代码的每个新步骤都必须以失败的断言开始!事实上,我并不在乎它是否是递归的。可以采用遍历的方法,但我只是想找到一个测试,如果方法不是递归的,它就会失败…谢谢。。。我是TDD新手,尝试自学,部分使用了“TDD使用Python”一书。本书区分了“功能测试”和“单元测试”。作者通过说功能测试从应用程序用户的PoV测试东西来描述差异,而单元测试从程序员的PoV测试东西。本书的“哲学”是,开发的每一步(理想情况下)都应该首先从失败的测试开始。这很难,但它似乎产生了强劲的结果!顺便说一句,我并不是特别想避免递归。@MikCorvent:函数的实现方式对两个焦点都没有关系。最终用户不在乎,他们只是想要一个工作程序。为了保持测试的灵活性,您希望单元测试只测试功能,而不是特定的实现。这样,您可以轻松地交换实现,并且仍然使用现有测试测试新的实现。谢谢,这很有意义。谢谢。。。是的,便士开始下降了!