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


73

我正在尝试简化我的作业问题之一,并使代码更好一点。我正在使用的是二进制搜索树。现在,我的Tree()班级中有一个函数可以查找所有元素并将它们放入列表中。

tree = Tree()
#insert a bunch of items into tree

然后我使用makeList()函数从树中取出所有节点,并将它们放入列表中。要调用该makeList()函数,我要做tree.makeList(tree.root)。对我来说,这似乎有些重复。我已经用调用了树对象,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
您想在模块级方法中使用“自我”吗?这绝对不会引起任何注意。如果makeList2()是类的方法,请提供正确的代码,而不提供没有上下文的摘要。
Andreas Jung

makeList2()应该是makeList(),我对其进行了编辑
chrisheinze 2011年

这怎么没有道理?我试图通过对树的根使用默认参数来简化我的makeList()函数,而不必调用它。
chrisheinze 2011年

1
我同意@ crh878,这是有道理的。我自己尝试过,也用于创建二进制搜索树。不开玩笑...
grisaitis

Answers:


53

拉尔斯曼人回答了您的第一个问题

对于第二个问题,您能否在跳转之前简单地看一下以避免递归?

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

48

它不起作用,因为默认参数是在函数定义时而不是在调用时求值的:

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

我强烈建议您不要制作foo(1, None)foo(1)做其他事情。
格伦·梅纳德

@Glenn:具有一个必须处理任意对象的单参数函数,有时可能很有意义。
Fred Foo

好的,我知道为什么它不起作用,以及您的第一个代码段如何不断添加您添加的任何值,但我没有完全了解第二个代码段中的情况。
chrisheinze 2011年

@ crh878:关于使用的要点None是最重要的。第二部分构造一个对象NOTHING,将其用作默认参数,并检查是否传入了确切的对象。如果隐藏NOTHING(不从模块中导出它),则客户端代码无法传递该对象。is通过内存地址比较对象。
Fred Foo

1

如果要将其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="!!!")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.