2010-03-14 9 views
1

Je suis en train de définir une fonction pour faire quelque chose comme çatransmettre les données auto dans une fonction récursive

def __binaryTreeInsert(self, toInsert, currentNode=getRoot(), parentNode=None): 

où le nœud actuel commence en tant que root, puis nous changeons à un autre nœud dans la méthode et appelez-le récursivement.

Cependant, je ne peux pas obtenir 'currentNode = getRoot()' pour fonctionner. Si j'essaie d'appeler la fonction getRoot() (comme ci-dessus), elle dit ne pas lui donner toutes les variables requises, mais si j'essaie d'appeler self.getRoot(), elle se plaint que self est une variable indéfinie. Est-ce que je peux faire ceci sans avoir à spécifier la racine en appelant cette méthode?

EDIT: Le cas de base de cette méthode est déjà

if currentNode == None: 

si l'aide que pour définir la racine ne fonctionnerait pas

+0

Il me semble très étrange que 'getRoot' est évidemment une fonction au niveau du module prise pas d'arguments? Utilisez-vous l'espace de noms global du module quand vous voulez une instance de classe, ou avez-vous oublié le 'self', ou est-ce que je manque quelque chose? –

+0

'None 'est généralement préféré à' == None'. –

+0

Les méthodes '__foo' devraient généralement être évitées. Ils ne font rien de privé (c'est impossible en Python), mais ils peuvent rendre le sous-classement et les tests plus difficiles. –

Répondre

2

Bien que arg=None est la valeur sentinelle Python idiomatique pour un argument non fourni, il n'a pas pour être None. Dans Lua, par exemple, l'argument idiomatique non fourni est une table vide. Nous pouvons effectivement l'appliquer à ce cas:

class Foo: 
    sentinel = {} 
    def bar(self, arg=sentinel): 
     if arg is self.sentinel: 
      print "You didn't supply an argument!" 
     else: 
      print "The argument was", arg 

f = Foo() 
f.bar(123) 
f.bar() 
f.bar(None) 
f.bar({}) 

Sortie:

 
The argument was 123 
You didn't supply an argument! 
The argument was None 
The argument was {} 

Cela fonctionne pour tous les cas, sauf explicitement le passage Foo.sentinel, parce Foo.sentinel est garanti d'avoir une adresse unique - sens, x is Foo.sentinel est seulement vrai lorsque x estFoo.sentinel :) Ainsi, en raison de la fermeture que nous avons créée autour de Foo.sentinel, il n'y a qu'un seul objet qui peut créer une situation ambiguë, un d il ne sera jamais utilisé par accident.

+0

Ce que je cherchais. Je veux en partie faire ceci pour l'abstraction plus loin, mais la plupart du temps j'étais simplement curieux si/comment cela pourrait être fait. – vimalloc

+0

Héritez toujours 'object' plutôt que rien pour utiliser des classes de style nouveau. –

+0

@Mike La classe dans laquelle cette méthode est hébergée hérite de l'objet – vimalloc

0

Vous pouvez faire

def __binaryTreeInsert(self, toInsert, currentNode=None, parentNode=None): 
    if currentNode is None: 
     currentNode = self.getRoot() 

... 
+0

Je pensais que cela, mais le problème est le cas de base de la récursion est « si curentNode est None: » il ne fonctionnerait pas avec le reste de la méthode – vimalloc

+0

@user, vous allez donner plus info alors. Si vous regardez cela, vous pouvez toujours vérifier par la suite si c'est «None» ou non. – voyager

+0

'None' est juste une valeur sentinelle ici, vous pouvez utiliser un objet arbitraire à la place si le cas' currentNode is None' a déjà une signification ... vous pouvez utiliser, par exemple, 'False' ou 'True'. –

-1
def __binaryTreeInsert(self, toInsert, currentNode=0, parentNode=None): 
    if not currentNode: 
     currentNode = self.getRoot() 
0

Lorsqu'une fonction ou une méthode est définie, la ligne def est immédiatement évaluée, y compris tous les mots-clés. Pour cette raison, des choses comme les appels de fonction et les objets mutables ne sont généralement pas appropriés pour les arguments par défaut.

La solution consiste plutôt à utiliser une valeur sentinelle. None est le plus courant, mais pour les cas qui None serait une valeur valide, vous pouvez utiliser une autre sentinelle, par exemple:

not_provided = object() 
def _binaryTreeInsert(self, toInsert, currentNode=not_provided, parentNode=None): 
    if currentNode is not_provided: 
     currentNode = self.getRoot()