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

Posted

技术标签:

【中文标题】使用 self.xxxx 作为默认参数 - Python【英文标题】:Using self.xxxx as a default parameter - Python 【发布时间】:2011-04-05 16:50:27 【问题描述】:

我正在尝试简化我的一个作业问题并使代码更好一些。我正在使用的是二叉搜索树。现在我的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 

【问题讨论】:

你想在模块级方法中使用“self”做什么?这绝对让人看不到。如果 makeList2() 是类的方法,那么请提供正确的代码,而不是没有上下文的 sn-ps。 makeList2() 应该是 makeList(),我编辑了它 这怎么没有意义?我试图通过使用树根的默认参数而不是调用它来更简单地使用我的 makeList() 函数。 我同意@crh878 的观点,这是有道理的。我自己尝试过,也用于创建二叉搜索树。不开玩笑... Using self.* as default value for a method的可能重复 【参考方案1】:

larsmans answered你的第一个问题

对于你的第二个问题,你可以在跳跃之前简单地查看以避免递归吗?

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

【讨论】:

【参考方案2】:

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

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.

【讨论】:

您可以省略Sentinel。只需使用NOTHING = object()。保证产生一个独特的单例,您可以通过 is 进行检查。 我强烈建议不要让foo(1, None)foo(1) 做不同的事情。 @Glenn:使用必须处理任意对象的单参数函数,它有时是有意义的。 好的,我明白为什么它不起作用,以及你的第一个代码段如何不断地附加你添加的任何值,但我没有完全关注第二个代码段中发生的事情。 @crh878:使用None这一点最重要。第二部分构造一个对象NOTHING,将其用作默认参数并检查是否传入了该确切对象。如果隐藏NOTHING(不要从您的模块中导出它),它不能被客户端传入代码。 is 按内存地址比较对象。【参考方案3】:

如果您想将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

【讨论】:

以上是关于使用 self.xxxx 作为默认参数 - Python的主要内容,如果未能解决你的问题,请参考以下文章

使用默认参数调用异步函数作为参数检查处理同步的函数?

Python之在函数中使用列表作为默认参数

默认泛型可作为参数正常使用,但不能作为函数参数的返回类型使用

如何在 Python 中使用类变量作为默认参数值

我可以在 Swift 中使用运算符作为默认函数参数吗?

使用类成员作为成员函数的默认参数