2009-05-13 7 views
1

Plus tôt aujourd'hui, j'ai demandé à un question de transmettre des valeurs de dictionnaire à une fonction. Bien que je comprenne maintenant comment accomplir ce que j'essayais d'accomplir, la question pourquoi (qui n'a pas été posée) n'a jamais été résolue. Donc, mon suivi est pourquoi je ne peuxPourquoi ne puis-je pas transmettre une référence directe à une valeur de dictionnaire à une fonction?

def myFunction(newDict['bubba']): 
    some code to process the parameter 

Est-ce simplement parce que les règles de l'analyseur ne permettent pas? J'ai recherché sur Google + Python + fonction + "paramètres permis" et n'ai rien trouvé d'utile donc j'apprécierais n'importe quelle information.

Je simplifie à l'excès ce qui se passe. J'ai un dictionnaire qui est structuré comme

myDict={outerkey1:(innerkey1:value,innerkey2:value,. . .innerkeyn:value),outerkey2:(innerkey1:value,innerkey2:value,. . .innerkeyn:value),. . .} 

Comme je l'ai dit, je sais comment faire ce que je voulais-je obtenu une réponse très utile. Mais je commençais à me demander pourquoi

def myFunction(outerkey,myDict[outerkey]): 

donne une erreur de syntaxe qui finement me est apparu que ce doit être un problème d'analyse syntaxique.

Répondre

6

Oui, l'analyseur rejettera ce code.

Les listes de paramètres sont utilisées dans les définitions de fonction pour lier des identifiants dans la fonction à des arguments transmis depuis l'extérieur lors de l'appel. Puisque newDict['bubba'] n'est pas un identificateur valide, cela n'a aucun sens - vous devez le fournir comme un argument d'invocation au lieu d'un paramètre de fonction, puisque les paramètres de la fonction ne peuvent être que des identifiants.

Parce que vous semblez intéressé par le formal grammar, voici les parties pertinentes:

funcdef ::= 
      [decorators] "def" funcname "(" [parameter_list] ")" 
       ":" suite 

parameter_list ::= 
       (defparameter ",")* 
       (~~"*" identifier [, "**" identifier] 
       | "**" identifier 
       | defparameter [","]) 

defparameter ::= 
      parameter ["=" expression] 

identifier ::= 
      (letter|"_") (letter | digit | "_")* 

En fait, la construction que vous essayez d'utiliser comme identifiant est un abonnement:

subscription ::= 
      primary "[" expression_list "]" 
+0

Merci, cela donnera une lecture intéressante plus tard. – PyNEwbie

+0

newDict ['bubba'] n'est pas un identifiant valide Je suppose que l'apprentissage de la lecture de la grammaire aidera à comprendre cela. Quand j'ai commencé cette ligne, j'ai décidé que ça devrait marcher parce que quand la fonction est appelée, newDict ['bubba'] fait référence à la chose sur laquelle je voulais que la fonction agisse. La solution était d'utiliser ** devant la référence dans l'appel et d'utiliser ** devant un nom dans la définition comme d'autres l'ont décrit mais je n'ai pas compris (et je ne fais maintenant que superficiellement) jusqu'à ce que répondre. J'espère que quand je m'ennuierai et que je lirai la grammaire, j'apprendrai encore plus merci – PyNEwbie

+1

En Python, les identifiants (noms d'objets) ne peuvent contenir que des lettres, des chiffres et des traits de soulignement. Si la grammaire devait permettre 'newDict ['bubba']' comme un symbole qui nomme un objet, il aurait du mal à faire la différence entre les symboles qui nomment les objets et l'opération d'indice sur les listes/dictionnaires. De plus, si vous pouviez utiliser 'newDict ['bubba']' comme identificateur, cela créerait de la confusion, car 'newDict' n'est pas un identifiant valide, même s'il semble que vous puissiez y indexer quelque chose. – cdleary

2

Il On dirait que vous pourriez être confondu entre la définition d'une fonction et appelant cette fonction. En guise d'exemple simple:

def f(x): 
    y = x * x 
    print "x squared is", y 

En soi, cette fonction ne fait rien (c'est-à-dire qu'elle n'imprime rien). Si vous mettez ceci dans un fichier source et l'exécutez, rien ne sera produit. Mais si vous ajoutez:

f(5) 

vous obtiendrez la sortie « x au carré est de 25 ». Lorsque Python rencontre le nom de la fonction suivi des paramètres réels , il remplace la (les) valeur (s) de ces paramètres réels par le (s) paramètre (s) formel dans la définition de la fonction. Dans ce cas, le paramètre formel est appelé x. Ensuite Python exécute la fonction f avec la valeur de x comme 5. Maintenant, le grand avantage est que vous pouvez utiliser à nouveau la même fonction avec une valeur différente:

f(10) 

imprime « x au carré est de 100 ».J'espère avoir bien compris la source de votre problème.

+0

Non je pense que je comprends la différence que je voulais définir ma fonction et plus tard pour la clé dans myDict: résultat = myFunction (outerKey, myDict [innerKey]) Comme je l'ai dit j'ai eu une bonne réponse, je voulais savoir pourquoi mon approche originale n'a pas fonctionné – PyNEwbie

2

Vous ne pouvez transmettre que des références à des objets.

a = { 'a' : 123, 'b' : [ 1, 2, 3 ] } 

def f(dictionary_value): 
    dictionary_value.append(4) 

f(a['b']) 

Ce que vous attendez. L'élément de dictionnaire a['b'] est passé "par référence" à la fonction f qui met à jour l'élément de dictionnaire.

+0

Ceci est intéressant et semble plus simple que la solution avec laquelle j'ai travaillé aujourd'hui et cela fonctionne. Cool So Puis-je avoir deux réponses acceptées? – PyNEwbie

+0

Il passe un * type de référence * (une liste). Si vous deviez passer un ['a'] de cette manière, l'exécution de dictionary_value + = 2 n'affecterait pas un ['a']. Il est important de comprendre la différence entre la valeur et les types de référence! – cdleary

+1

Tout est une référence. Il n'y a pas de distinction utile entre "types de référence" et "types de valeur". Cependant, certains types sont immuables. L'immutabilité les fait ressembler à des types «valeur» en Java ou en C++. –

Questions connexes