Pourquoi les arguments non par défaut ne peuvent-ils pas suivre les arguments par défaut?

138

Pourquoi ce morceau de code lève-t-il une SyntaxError?

  >>> def fun1(a="who is you", b="True", x, y):
...     print a,b,x,y
... 
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument

Alors que le morceau de code suivant s'exécute sans erreurs visibles:

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 
pointillé
la source
en python c'est comme ça que la structure est lorsque vous définissez une fonction def myfunction(position_arguments, *arguments, **keywords):`....`
abhishekgarg

Réponses:

172

Tous les paramètres requis doivent être placés avant les arguments par défaut. Simplement parce qu'ils sont obligatoires, alors que les arguments par défaut ne le sont pas. D'un point de vue syntaxique, il serait impossible pour l'interpréteur de décider quelles valeurs correspondent à quels arguments si les modes mixtes étaient autorisés. A SyntaxErrorest levé si les arguments ne sont pas donnés dans le bon ordre:

Jetons un coup d'œil aux arguments de mots clés, en utilisant votre fonction.

def fun1(a="who is you", b="True", x, y):
...     print a,b,x,y

Supposons qu'il soit autorisé à déclarer la fonction comme ci-dessus, puis avec les déclarations ci-dessus, nous pouvons faire les appels d'argument positionnel ou mot-clé suivants (réguliers):

func1("ok a", "ok b", 1)  # Is 1 assigned to x or ?
func1(1)                  # Is 1 assigned to a or ?
func1(1, 2)               # ?

Comment vous suggérerez l'affectation de variables dans l'appel de fonction, comment les arguments par défaut seront utilisés avec les arguments de mots-clés.

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 

Référence O'Reilly - Core-Python
Où que cette fonction utilise les arguments par défaut syntaxiquement corrects pour les appels de fonction ci-dessus. L'appel d'arguments de mots-clés s'avère utile pour pouvoir fournir des arguments de position dans le désordre, mais, couplés aux arguments par défaut, ils peuvent également être utilisés pour "ignorer" les arguments manquants.

Rahul Gautam
la source
4
<q> D'un point de vue syntaxique, il serait impossible pour l'interpréteur de décider quelles valeurs correspondent aux arguments si les modes mixtes étaient autorisés. </q> Ruby autorise les arguments non par défaut après ceux par défaut. <q> Comment vous suggérerez l'affectation de variables dans l'appel de fonction </q> Il suffit d'utiliser func1(x=1, y=2).
faible
Salut @weakish, merci pour le commentaire, Python a un bon moyen d'y parvenir, veuillez rechercher * args et ** kwargs
Rahul Gautam
Salut @Rahul Gautam Je suis confus. Je pensais que je **kwargsne pouvais pas faire def fun1(a="who is you", b="True", x, y)un travail similaire. Si vous utilisez def f(**kwargs), vous devez gérer les valeurs par défaut dans le corps?
faible
@weakish def fun1(a="who is you", b="True", x, y)la même chose soit réalisée avec un style différent. if def fun1 (** kwrgs) `alors appeler fun1({'a': 'who is you', 'b': True})pas besoin de passer x et y.
Rahul Gautam
2
Pourquoi écrivez-vous "Syntaxiquement, il serait impossible pour l'interpréteur de décider quelles valeurs correspondent à quels arguments si les modes mixtes étaient autorisés."? Je pense que l'algorithme de PEP 3102 pourrait fonctionner exactement de la même manière même s'il def foo(x=None, y)était autorisé. Je suis donc toujours curieux de savoir pourquoi cela n'est pas autorisé par Python. Y a-t-il une vraie raison fondamentale ou est-ce simplement "nous ne le permettons pas parce que nous ne le permettons pas".
Jeroen Demeyer
15
SyntaxError: non-default argument follows default argument

Si vous autorisiez cela, les arguments par défaut seraient rendus inutiles car vous ne pourrez jamais utiliser leurs valeurs par défaut, puisque les arguments non par défaut viennent après .

Cependant, dans Python 3, vous pouvez effectuer les opérations suivantes:

def fun1(a="who is you", b="True", *, x, y):
    pass

qui fait xet ymot - clé uniquement pour que vous puissiez le faire:

fun1(x=2, y=2)

Cela fonctionne car il n'y a plus d'ambiguïté. Notez que vous ne pouvez toujours pas faire fun1(2, 2)(cela définirait les arguments par défaut).

Jamylak
la source
Les arguments de mots-clés uniquement sont une fonctionnalité intéressante de Python 3. Dommage que le correctif pour les rétroporter vers Python 2.6 et 2.7 vient d'expirer .
Nick Chammas
10

Permettez-moi de clarifier deux points ici:

  • tout d'abord, un argument non par défaut ne doit pas suivre l'argument par défaut, cela signifie que vous ne pouvez pas définir (a = b, c) en fonction l'ordre de définition du paramètre en fonction:
    • paramètre de position ou paramètre non par défaut, c.-à-d. (a, b, c)
    • paramètre de mot-clé ou paramètre par défaut ie (a = "b", r = "j")
    • paramètre de mot clé uniquement ie (* args)
    • paramètre var-keyword ie (** kwargs)

def example(a, b, c=None, r="w" , d=[], *ae, **ab):

(a, b) sont des paramètres de position

(c = aucun) est un paramètre facultatif

(r = "w") est le paramètre de mot clé

(d = []) est le paramètre de liste

(* ae) est un mot clé uniquement

(** ab) est le paramètre var-keyword

  • maintenant, la chose secondaire est si j'essaye quelque chose comme ceci: def example(a, b, c=a,d=b):

L'argument n'est pas défini lorsque les valeurs par défaut sont enregistrées, Python calcule et enregistre les valeurs par défaut lorsque vous définissez la fonction

c et d ne sont pas définis, n'existe pas, lorsque cela se produit (il n'existe que lorsque la fonction est exécutée)

"a, a = b" n'est pas autorisé en paramètre.

Aaditya Ura
la source
0

Les arguments requis (ceux sans valeurs par défaut) doivent être au début pour permettre au code client de n'en fournir que deux. Si les arguments optionnels étaient au début, ce serait déroutant:

fun1("who is who", 3, "jack")

Qu'est-ce que cela ferait dans votre premier exemple? Dans le dernier, x est "qui est qui", y est 3 et a = "jack".

cforbish
la source