使用self.xxxx作为默认参数 - Python

93

我正在尝试简化我的一道作业题,并让代码更好。我正在使用二叉搜索树。目前,在我的Tree()类中,我有一个函数,它可以找到所有的元素并将它们放入列表中。

tree = Tree()
#insert a bunch of items into tree
然后我使用我的makeList()函数将树中的所有节点放入列表中。 要调用makeList()函数,我执行tree.makeList(tree.root)。对我来说,这似乎有点重复。我已经用tree.调用了tree对象,所以tree.root只是浪费一点打字时间。
现在makeList函数如下:
    def makeList(self, aNode):
        if aNode is None:
            return []
        return [aNode.data] + self.makeList(aNode.lChild) + self.makeList(aNode.rChild)

我希望将aNode输入参数设置为默认参数,例如aNode = self.root(不起作用),这样我就可以使用 tree.makeList() 来运行函数。

第一个问题是,为什么这不起作用?
第二个问题是,有没有办法让它起作用?如您所见,makeList() 函数是递归的,因此我无法在函数开头定义任何内容,否则会导致无限循环。

编辑 这里是所有代码,如请求所示:

class Node(object):
    def __init__(self, data):
        self.data = data
        self.lChild = None
        self.rChild = None

class Tree(object):
    def __init__(self):
        self.root = None

    def __str__(self):
        current = self.root

    def isEmpty(self):
        if self.root == None:
            return True
        else:
            return False

    def insert (self, item):
        newNode = Node (item)
        current = self.root
        parent = self.root

        if self.root == None:
            self.root = newNode
        else:
            while current != None:
                parent = current
                if item < current.data:
                    current = current.lChild
                else:
                    current = current.rChild

            if item < parent.data:
                parent.lChild = newNode
            else:
                parent.rChild = newNode

    def inOrder(self, aNode):
        if aNode != None:
            self.inOrder(aNode.lChild)
            print aNode.data
            self.inOrder(aNode.rChild)

    def makeList(self, aNode):
        if aNode is None:
            return []
        return [aNode.data] + self.makeList(aNode.lChild) + self.makeList(aNode.rChild)


    def isSimilar(self, n, m):
        nList = self.makeList(n.root)
        mList = self.makeList(m.root) 
        print mList == nList 

1
在模块级别方法中,你想要使用'self'有什么意义呢?这完全没有意义。如果makeList2()是一个类的方法,请提供正确的代码,而不是没有上下文的片段。 - user2665694
makeList2() 应该是 makeList(),我已经编辑过了。 - chrisheinze
这怎么说不通?我试图通过在树的根部使用默认参数来简化我的makeList()函数,而不是不断地调用它。 - chrisheinze
1
我同意 @crh878 的观点,这是有道理的。我自己也尝试过,用于创建二叉搜索树。不开玩笑... - william_grisaitis
3个回答

67

larsmans 回答了你的第一个问题。

对于你的第二个问题,你是否可以先看一眼再跳,以避免递归呢?

def makeList(self, aNode=None):
    if aNode is None:
        aNode = self.root
    treeaslist = [aNode.data]
    if aNode.lChild:
        treeaslist.extend(self.makeList(aNode.lChild))
    if aNode.rChild:
        treeaslist.extend(self.makeList(aNode.rChild))
    return treeaslist

62

它不起作用是因为默认参数在函数定义时进行评估,而不是在调用时进行评估:

def f(lst = []):
    lst.append(1)
    return lst

print(f()) # prints [1]
print(f()) # prints [1, 1]

一种常见的策略是使用None作为默认参数。如果 None 是有效值,则使用单例标记:

NOTHING = object()

def f(arg = NOTHING):
    if arg is NOTHING:
        # no argument
    # etc.

1
你可以省略 Sentinel。只需使用 NOTHING = object()。保证通过 is 检查可获得唯一的单例。 - user395760
@Glenn:对于必须处理任意对象的单参数函数,有时这是有意义的。 - Fred Foo
好的,我明白为什么它不起作用,也知道你的第一个代码段如何不断地附加任何添加的值,但是我还没有完全理解第二个代码段中发生了什么。 - chrisheinze
为什么我们应该使用这个而不是None? - Charlestone
如果需要将None用于其他含义,请使用@Charlestone。 - Ben Farmer
显示剩余4条评论

2
如果你想将None视为有效的参数,可以使用**kwarg参数。最初的回答。
def function(arg1, arg2, **kwargs):
    kwargs.setdefault('arg3', default)
    arg3 = kwargs['arg3']
    
    # Continue with function

function("amazing", "fantastic") # uses default
function("foo", "bar", arg3=None) # Not default, but None
function("hello", "world", arg3="!!!")

我曾经也看到过...或其他单例被这样使用。翻译成中文为:

我也见过...或其他单例被这样使用。


def function(arg1, arg2=...):
    if arg2 is ...:
        arg2 = default

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接