Python 在递归函数的开头声明空变量
我读过,你永远不应该测试变量的存在;如果您的程序必须检查变量是否存在,则您不“知道您的变量”,这是一个设计错误。但是,我有一个递归函数,在每次调用该函数时向字典和列表添加值。为了避免声明全局变量,我试图使变量成为函数的局部变量。但是为了做到这一点,我必须在函数的开头将myList和myDict声明为[]和{}。当然,这会删除我在以前的递归调用中对dict和list所做的更改,这是我不想要的。我想试试。。。在开始时捕获,检查变量是否存在,如果它们还不存在,则只将它们声明为{}和[],但我读到这是一个糟糕的设计。有没有更好的办法?我很抱歉没有附加任何实际的代码,但我仍处于规划此函数的开始阶段,因此没有什么需要附加的 创建新的局部变量不会覆盖以前调用的局部变量。每次调用函数时,都会得到新的局部变量。如果函数递归地调用自身,则每个调用都将获得自己的局部变量。从你的解释很难判断这是否是你问题的答案。你真的需要发布一些代码。这里有一个你可以利用的工具。默认的可变参数(如字典或列表)将在递归中发生变化:Python 在递归函数的开头声明空变量,python,Python,我读过,你永远不应该测试变量的存在;如果您的程序必须检查变量是否存在,则您不“知道您的变量”,这是一个设计错误。但是,我有一个递归函数,在每次调用该函数时向字典和列表添加值。为了避免声明全局变量,我试图使变量成为函数的局部变量。但是为了做到这一点,我必须在函数的开头将myList和myDict声明为[]和{}。当然,这会删除我在以前的递归调用中对dict和list所做的更改,这是我不想要的。我想试试。。。在开始时捕获,检查变量是否存在,如果它们还不存在,则只将它们声明为{}和[],但我读到这是一
def my_function(d={}):
...
#recursion will mutate d
小心使用,但它可能有用
一个简单的例子:
def f(a,d=[]):
d.append(a)
if a!=2:
f(2)
return d
print f(1) # [1,2]
如果您确实需要访问递归函数中的可变状态,您可能应该使用一个类 在这种情况下,使用不支持面向对象编程(OOP)的语言时,最好的方法通常只是使用全局变量,可能包含在它们自己的模块中,以避免名称空间冲突。全局变量是“坏的”,但有时它们是两个(或更多)邪恶中的较小者。但是您正在用Python编写代码,它为您提供了一组丰富的OOP构造。你应该使用它们 例如,这里有一个简单的递归Fibonacci函数,它使用memonization来避免原始版本的O(2^n)复杂性(请注意,前导下划线仅表示名称为“private”,在没有详细了解其内部工作原理的情况下不应使用): 快速测试;请注意,第二次呼叫返回时没有明显延迟:
>>> map(fib, xrange(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
>>> fib(249)
4880197746793002076754294951020699004973287771475874L
您可以看到,这个“函数”(实际上是一个可调用对象)通过在创建可变对象时创建它来解决您描述的问题。然后它通过self
访问可变对象。有比上面更好的方法来编写fib
,但是对于需要状态的更复杂的递归函数来说,这可能是一个很好的基本设计
当然你还有很多其他选择。使用另一个答案中提到的可变默认值非常类似——但我更喜欢使用类,因为它更显式。您甚至可以将对象存储为函数的属性
def foo(a, b):
if base_case(a, b):
return
foo.dct[a] = b
foo.lst.append((a, b))
foo(a - 1, b - 1)
foo.dct = {}
foo.lst = []
我不喜欢这个建筑,但它值得了解。最后,不要完全忽视最明显的解决方案:
def foo(a, b, dct, lst):
if base_case(a, b):
return
dct[a] = b
lst.append((a, b))
foo(a - 1, b - 1, dct, lst)
有时候这其实是最好的方式!这当然是简单明了的
最后,我要指出,您似乎误解了功能范围的性质。你说
我想试试。。。在开始时捕获,检查变量是否存在,如果它们还不存在,则只将它们声明为{}和[],但我读到这是一个糟糕的设计
这个设计不错。这是一个破设计,根本不起作用。如果您的字典和列表不是全局的,那么您的try/except
将始终引发异常,因为在函数的开头,没有定义任何局部变量
这让我想到了最后一点。也许您希望在每次最初调用函数时创建一个新的字典和列表,并在递归停止后丢弃它们。在这种情况下,必须调整上面基于类的选项;或者,您可以将递归函数包装在外部函数中,以便在每次调用时重新创建它们:
def outer(a, b):
return _inner_recursive(a, b, {}, [])
def _inner_recursive(a, b, lst, dct):
#blah blah blah
“我读过,你永远不应该测试变量的存在……”永远不要说“永远”。另外,如何显示您的代码?我的直觉是,可能有更好的方法来做到这一点。
def outer(a, b):
return _inner_recursive(a, b, {}, [])
def _inner_recursive(a, b, lst, dct):
#blah blah blah