Verwenden von self.xxxx als Standardparameter - Python

73

Ich versuche, eines meiner Hausaufgabenprobleme zu vereinfachen und den Code ein wenig zu verbessern. Ich arbeite mit einem binären Suchbaum. Im Moment habe ich eine Funktion in meiner Tree()Klasse, die alle Elemente findet und in eine Liste einfügt.

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

dann benutze ich meine makeList () Funktion, um alle Knoten aus dem Baum zu nehmen und sie in eine Liste zu setzen. Um die makeList()Funktion aufzurufen , tue ich tree.makeList(tree.root). Für mich scheint sich das ein wenig zu wiederholen. Ich rufe das Baumobjekt bereits mit auf, tree.daher tree.rootist das nur eine Verschwendung von ein wenig Tippen.

Im Moment lautet die Funktion makeList:

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

Ich möchte die aNode-Eingabe zu einem Standardparameter machen, wie aNode = self.root(was nicht funktioniert), damit ich die Funktion damit ausführen kann tree.makeList().

Die erste Frage ist, warum das nicht funktioniert.
Die zweite Frage ist, gibt es eine Möglichkeit, wie es funktionieren kann? Wie Sie sehen, ist die makeList()Funktion rekursiv, sodass ich am Anfang der Funktion nichts definieren kann oder eine Endlosschleife erhalte.

BEARBEITEN Hier ist der gesamte angeforderte Code:

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 
chrisheinze
quelle
1
Was möchten Sie mit 'self' innerhalb einer Methode auf Modulebene? Das macht absolut keinen Anblick. Wenn makeList2 () eine Klassenmethode ist, geben Sie bitte den richtigen Code und keine Snippets ohne Kontext an.
Andreas Jung
makeList2 () sollte makeList () sein, ich habe es bearbeitet
chrisheinze
Wie macht das keinen Sinn? Ich versuche, meine Funktion makeList () einfacher zu verwenden, indem ich einen Standardparameter für die Wurzel des Baums verwende, anstatt ihn aufrufen zu müssen.
Chrisheinze
1
Ich stimme @ crh878 zu, dass dies sinnvoll ist. Ich habe es selbst versucht, auch um einen binären Suchbaum zu erstellen. Kein Witz ...
Grisaitis
1
Mögliches Duplikat von Verwenden von self. * Als Standardwert für eine Methode
Stevoisiak

Antworten:

53

Larsmans beantwortete Ihre erste Frage

Können Sie bei Ihrer zweiten Frage einfach nachsehen, bevor Sie springen, um eine Rekursion zu vermeiden?

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
Nofinator
quelle
48

Dies funktioniert nicht, da Standardargumente zur Funktionsdefinitionszeit und nicht zur Aufrufzeit ausgewertet werden:

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

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

Die übliche Strategie besteht darin, einen NoneStandardparameter zu verwenden . Wenn Nonees sich um einen gültigen Wert handelt, verwenden Sie einen Singleton-Sentinel:

NOTHING = object()

def f(arg = NOTHING):
    if arg is NOTHING:
        # no argument
    # etc.
Fred Foo
quelle
1
Sie können das weglassen Sentinel. Einfach benutzen NOTHING = object(). Garantiert einen einzigartigen Singleton, nach dem Sie suchen können is.
Ich würde dringend davon abraten, verschiedene Dinge zu machen foo(1, None)und zu foo(1)tun.
Glenn Maynard
@Glenn: Mit einer One-Arg-Funktion, die sich mit beliebigen Objekten befassen muss, kann dies manchmal sinnvoll sein.
Fred Foo
Ok, ich verstehe, warum es nicht funktioniert und wie Ihr erstes Codesegment kontinuierlich den Wert anfügt, den Sie hinzufügen, aber ich verfolge nicht vollständig, was im zweiten Codesegment vor sich geht.
Chrisheinze
@ crh878: Der Punkt über die Verwendung Noneist der wichtigste. Der zweite Teil erstellt ein Objekt NOTHING, verwendet dieses als Standardargument und prüft, ob das genaue Objekt übergeben wurde. Wenn Sie es ausblenden NOTHING(nicht aus Ihrem Modul exportieren), kann es nicht vom Clientcode übergeben werden. isvergleicht Objekte nach Speicheradresse.
Fred Foo
1

Wenn Sie Noneals gültiges Argument behandeln möchten , können Sie einen **kwargParameter verwenden.

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="!!!")
Killjoy
quelle