使用 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的主要内容,如果未能解决你的问题,请参考以下文章