简体   繁体   English

递归python函数中的持久对象

[英]Persistent objects in recursive python functions

I am trying to write a recursive function that needs to store and modify an object (say a set) as it recurses. 我正在尝试编写一个递归函数,需要在递归时存储和修改对象(比如一个集合)。 Should I use a global name inside the function? 我应该在函数内部使用全局名称吗? Another option is to modify or inherit the class of the parameter of the function so that it can keep this persistent object but I don't find it elegant. 另一种选择是修改或继承函数参数的类,以便它可以保留这个持久对象,但我发现它并不优雅。 I could also use a stack if I would forgo the recursion altogether... 如果我完全放弃递归,我也可以使用堆栈...

Is there a pythonic way of doing this? 有这样做的pythonic方式吗? Could a generator do the trick? 发电机可以做到这一点吗?

Just pass through your persistent object through the recursive method. 只需通过递归方法传递持久对象。

def recursivemethod(obj_to_act_on, persistent_obj=None):

    if persistent_obj == None:
        persistent_obj = set()

    # Act on your object

    return recursivemethod(newobj, persistent_obj)

Pass the set into the recursive method as an argument, then modify it there before passing it to the next step. 将集合作为参数传递给递归方法,然后在将其传递到下一步之前将其修改。 Complex objects are passed by reference. 复杂对象通过引用传递。

Objects are passed by reference. 对象通过引用传递。 If you're only modifying an object, you can do that from within a recursive function and the change will be globally visible. 如果您只修改对象,则可以在递归函数中执行此操作,并且更改将全局可见。

If you need to assign a variable inside a recursive function and see it after the function returns, then you can't just assign a local variable with = . 如果需要在递归函数中分配变量并在函数返回后看到它,那么您不能只使用=分配局部变量。 What you can do is update a field of another object. 你可以做的是更新另一个对象的字段。

class Accumulator: pass

def foo():
    # Create accumulator
    acc = Accumulator()
    acc.value = 0

    # Define and call a recursive function that modifies accumulator
    def bar(n):
        if (n > 0): bar(n-1)
        acc.value = acc.value + 1
    bar(5)

    # Get accumulator
    return acc.value

If it's a container (not an immutable data type), you can pass the object through: 如果它是一个容器(不是不可变数据类型),则可以通过以下方式传递对象:

import random

def foo(bar=None, i=10):
    if bar is None:
        bar = set()
    if i == 0:
        return bar
    bar |= set(random.randint(1, 1000) for i in xrange(10))
    return foo(bar, i - 1)

random_numbers_set = foo()

(Don't ask me what that's meant to do... I was just typing random things :P) (不要问我这是做什么的......我只是在输入随机的东西:P)

如果您传递的对象是可变的,那么在更早的递归中将会看到更深层递归的更改。

  1. Use a variable global to the function. 对函数使用变量global。

  2. Pass the object around as an accumulator: 将对象作为累加器传递:

     def recurse(foo, acc=None): acc = {} recurse(acc) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM