有没有办法判断我是否在 Python 中使用递归?

发布于 2024-09-24 13:10:14 字数 255 浏览 6 评论 0原文

我正在编写一个函数来遍历用户的文件系统并创建一棵代表该目录的树(该树实际上是 Tkinter 中的 TreeView 小部件,但在功能上是一棵树)。

我能想到的最好的方法是递归。然而,我在函数中的一种情况要求我知道它是否是“原始”函数调用,在这种情况下文件没有父节点,或者它是否是“递归”函数调用,即已被调用的函数。由函数本身创建,以便我可以为这些文件提供适当的父节点。

Python 有没有办法询问一个函数,“嘿,你是递归的吗?”或者“嘿,你是从哪里打来的?”

I'm writing a function to traverse the user's file system and create a tree representing that directory (the tree is really a TreeView widget in Tkinter, but that's functionally a tree).

The best way I can think of doing this is recursion. However, one of my cases in the function requires me to know if it is the "original" function call, in which case the files have no parent node, or if it is a "recursive" function call, i.e. a call that has been made by the function itself, so that I can give those files an appropriate parent node.

Is there any way in Python to ask a function, "hey, are you recursive?" or "hey, where were you called from?"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

只有影子陪我不离不弃 2024-10-01 13:10:14

与其他所有语言几乎相同 - 在您的情况下,您传递对父级的引用并检查它是否为 None。如果是这样,您将创建一个适当的父节点。

Pretty much the same as in every other language - in your case, you pass a reference to the parent and check if it is None. If so, you create a proper parent node.

一身仙ぐ女味 2024-10-01 13:10:14

我在函数中的一个案例要求我知道它是否是“原始”函数调用,在这种情况下文件没有父节点

这似乎是特定函数需要太多工作的奇怪情况。你必须建造这棵树——为什么你需要知道它附着在哪里?为什么不直接构建您负责的节点并返回它们呢?

def make_tree(path):
    return [
        make_tree(os.path.join(path, element))
        for element in get_elements(path)]

当你收到它时,再次走动树吗?

如果你真的想集成它,只需传递父级:

def make_tree(path, parent_node = None):
    new_node = Node(...)
    for ....:
        make_tree(path+..., new_node)

    if parent_node is not None:
        parent_node.add(new_node)
    else:
        .....

one of my cases in the function requires me to know if it is the "original" function call, in which case the files have no parent node

This seems like a strange case of too much work for the specific function. You have to construct the tree - why do you need to know where it's attached? Why not just construct the nodes you're responsible for and return them?

def make_tree(path):
    return [
        make_tree(os.path.join(path, element))
        for element in get_elements(path)]

And walk the tree again when you receive it?

If you really want to integrate it, just pass the parent:

def make_tree(path, parent_node = None):
    new_node = Node(...)
    for ....:
        make_tree(path+..., new_node)

    if parent_node is not None:
        parent_node.add(new_node)
    else:
        .....
牛↙奶布丁 2024-10-01 13:10:14

在调用递归的同时包含对父级或某些级别信息的引用应该是简单且常见的。

另一种方法(不过我不喜欢)是使用 pythons inspect 模块,它可以让您检查例如调用堆栈。一个例子:

#!/usr/bin/env python

import inspect

def whocalled():
    return inspect.stack()[2][3]

def fib(n):
    print n, whocalled()
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

if __name__ == '__main__':
    fib(4)

会打印:

4 <module>
3 fib
2 fib
1 fib
0 fib
1 fib
2 fib
1 fib
0 fib

It should be easy and common, to include a reference to the parent or some level information along with the call to the recursion.

One other way (which I wouldn't prefer, though) is to use pythons inspect module, which lets you inspect e.g. the call stack. An example:

#!/usr/bin/env python

import inspect

def whocalled():
    return inspect.stack()[2][3]

def fib(n):
    print n, whocalled()
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

if __name__ == '__main__':
    fib(4)

Would print:

4 <module>
3 fib
2 fib
1 fib
0 fib
1 fib
2 fib
1 fib
0 fib
近箐 2024-10-01 13:10:14

您可以通过inspect模块访问内存堆栈。

import inspect

def whoami():
    '''Returns the function name of the caller.'''

    return inspect.stack()[1][3] #Stack data for the name of the function

def caller():
    '''Returns the caller of a function.'''

    return inspect.stack()[2][3] #Stack data for the name of whatever calls this

caller = caller()

如果您尝试从 __main__ 调用它,您将收到索引超出范围错误。

when the caller of the function != whoami() -> no longer recursing.

You can access the memory stack through the inspectmodule.

import inspect

def whoami():
    '''Returns the function name of the caller.'''

    return inspect.stack()[1][3] #Stack data for the name of the function

def caller():
    '''Returns the caller of a function.'''

    return inspect.stack()[2][3] #Stack data for the name of whatever calls this

caller = caller()

You'll get an index out of range error if you attempt to call it from __main__.

when the caller of the function != whoami() -> no longer recursing.
故人爱我别走 2024-10-01 13:10:14

我真的很奇怪你为什么把事情搞得这么复杂。您可以简单地将函数分为递归部分和非递归部分!这是一个简单的示例:

def countdown(n):
    " original function "
    print "Ok, start the countdown (not recursive)"

    msg = "We are at"

    def recursive( x ):
        " recursive part "
        if x >= 0:
            print msg, x, "(recursive)"
            return recursive(x-1)

    return recursive(n)

countdown(10)

实际上,您甚至不需要递归函数的许多参数,因为它是一个闭包,可以使用您在其名称空间中定义的任何内容。

I really wonder why you make this so complicated. You can simply split the function in a recursive and a not recursive part! Here is a simple example:

def countdown(n):
    " original function "
    print "Ok, start the countdown (not recursive)"

    msg = "We are at"

    def recursive( x ):
        " recursive part "
        if x >= 0:
            print msg, x, "(recursive)"
            return recursive(x-1)

    return recursive(n)

countdown(10)

In reality you don't even need many arguments to the recursive function because it is a closure and can use anything you defined in it's namespace.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文