Pourquoi les assignations ne sont-elles pas permises dans les expressions `lambda` de Python?

ceci n'est pas un duplicata de mission à l'intérieur lambda expression en Python, c'est à dire, je suis demandant comment tromper Python dans l'assignation d'un lambda expression.

j'ai un certain fond de calcul λ. Considérant le code suivant, il ressemble Python est tout à fait disposé à effectuer des effets secondaires lambda expressions:

#!/usr/bin/python

def applyTo42(f):
    return f(42)

def double(x):
    return x * 2

class ContainsVal:
    def __init__(self, v):
        self.v = v

    def store(self, v):
        self.v = v

def main():

    print('== functional, no side effects')

    print('-- print the double of 42')
    print(applyTo42(double))

    print('-- print 1000 more than 42')
    print(applyTo42(lambda x: x + 1000))

    print('-- print c's value instead of 42')
    c = ContainsVal(23)
    print(applyTo42(lambda x: c.v))


    print('== not functional, side effects')

    print('-- perform IO on 42')
    applyTo42(lambda x: print(x))

    print('-- set c's value to 42')
    print(c.v)
    applyTo42(lambda x: c.store(x))
    print(c.v)

    #print('== illegal, but why?')
    #print(applyTo42(lambda x: c.v = 99))

if __name__ == '__main__':
    main()

mais si je décommente les lignes

    print('== illegal, but why?')
    print(applyTo42(lambda x: c.v = 99))

je vais obtenez de l'

SyntaxError: lambda cannot contain assignment

Pourquoi pas? Quelle est la raison profonde derrière cela?

  • comme le code le démontre, il ne peut s'agir de" pureté " dans un sens fonctionnel.

  • la seule explication que je puisse imaginer est que les assignemts ne retourne rien, pas même None. Mais ça a l'air nul et aurait être facile à fixer (une façon: faire revenir les expressions lambda None si le corps est un déclaration.)

Pas de réponse:

  • Parce que c'est défini de cette façon (je veux savoir pourquoi il est défini de cette façon).

  • Parce que c'est dans la grammaire (voir ci-dessus).

  • Utiliser def si vous avez besoin d'instructions (je n'ai pas demander comment obtenir des instructions dans une fonction).

"Ce serait changer la syntaxe / langues / sémantique" devrait être ok, comme une réponse si vous pouvez venir avec un exemple d'un tel changement, et pourquoi il serait mauvais.

10
demandé sur jpp 2018-04-29 23:14:38

7 réponses

Le lambda existe, c'est que c'est une expression.1 Si vous voulez quelque chose qui est comme lambda mais c'est une déclaration, c'est juste def.

les expressions Python ne peuvent pas contenir de déclarations. C'est, en fait, fondamental pour le langage, et Python obtient beaucoup de kilométrage hors de cette décision. C'est la raison pour laquelle l'indentation pour le contrôle de flux fonctionne au lieu d'être grotesque comme dans beaucoup d'autres tentatives (comme CoffeeScript). C'est la raison pour laquelle vous pouvez lire l'état change en parcourant le premier objet de chaque ligne. C'est même une partie de la raison pour laquelle le langage est facile à analyser, à la fois pour le compilateur et pour les lecteurs humains.2

changer Python pour avoir un moyen d ' "échapper" à la déclaration-expression diviser, sauf peut-être d'une manière très prudente et limitée, le transformerait en un langage complètement différent, et un qui n'a plus eu beaucoup des avantages qui poussent les gens à choisir Python dans le premier lieu.

changer Python pour faire la plupart des expressions de déclarations (comme, disons, Ruby) le transformerait à nouveau en un langage complètement différent sans les avantages actuels de Python.

et si Python faire un de ces changements, alors il n'y aurait pas plus de raison pour lambda en premier lieu; 2,3 vous pouvez simplement utiliser def déclarations à l'intérieur d'une expression.


Qu'en est-il de changer Python à la place faire des attributions des expressions? Il devrait être évident que ça casserait "vous pouvez lire les changements d'état en parcourant le premier objet dans chaque ligne". Bien que Guido se concentre habituellement sur le fait que if spam=eggs est une erreur plus souvent qu'utile.

le fait que Python vous donne des moyens de contourner cela en cas de besoin, comme setattr ou même appeler explicitement __setitem__globals(), ne veut pas dire que c'est quelque chose qui devrait avoir un support syntaxique direct. Quelque chose qui est très rarement nécessaire ne mérite pas de sucre syntaxique-et encore plus pour quelque chose qui est assez inhabituel qu'il devrait élever des sourcils et/ou des drapeaux rouges quand il est réellement fait.


1. Je n'ai aucune idée si C'était la compréhension de Guido quand il a ajouté à l'origine lambda retour en Python 1.0. Mais c'est certainement la raison lambda n'a pas été supprimé dans Python 3.0.

2. En fait, Guido a, à plusieurs reprises, suggéré que permettre un analyseur LL (1) que les humains peuvent exécuter dans leurs têtes est une raison suffisante pour que le langage soit basé sur des énoncés, au point que d'autres avantages n'ont même pas besoin d'être discutés. j'ai écrit à ce sujet il y a quelques années si quelqu'un est intéressé.

3. Si vous vous demandez pourquoi tant de langues lambda expression malgré avoir déjà def: dans de nombreux langages, allant de C++ à Ruby, les fonctions ne sont pas objets de première classe qui peuvent être transmis, donc ils ont dû inventer une deuxième chose qui est de première classe mais fonctionne comme une fonction. Dans d'autres, de Smalltalk à Java, les fonctions ne sont même pas existe, seules les méthodes, encore une fois, ils ont dû inventer une deuxième chose qui n'est pas une méthode, mais fonctionne comme un. Python a aucun de ces problèmes.

4. Quelques langages, comme C# et JavaScript, avaient en fait des définitions de fonctions en ligne parfaitement fonctionnelles, mais ont ajouté une sorte de lambda syntaxe que pur sucre syntaxique, pour le rendre plus concis et moins boilerplatey. Cela pourrait en fait valoir la peine de le faire en Python (bien que chaque tentative de bonne syntaxe jusqu'à présent est tombée à plat), mais ce ne serait pas le courant lambda syntaxe, qui est presque aussi verbeuse que def.

13
répondu abarnert 2018-04-29 21:08:05

il y a un syntaxe problème: la cession est un déclaration, et le corps d'un lambda ne peut avoir expressions. La syntaxe de Python est conçue de cette façon1. Check it out https://docs.python.org/3/reference/grammar.html.

Il y a aussi un sémantique problème: qu'est-ce que chaque instruction return

ce n'est pas du tout impossible en python, en fait, il était parfois nécessaire de capturer des liages tardifs variables et sidestep par (ab)en utilisant kwargs(keyword arguments)

edit:

exemple de code

f = lambda x,a=1: (lambda c = a+2, b = a+1: (lambda e = x,d = c+1: print(a,b,c,d,e))())()

f("w")

# output 1 2 3 4 w

# expression assignment through an object's method call

if let(a=1) .a > 0 and let(b=let.a+1) .b != 1 and let(c=let.b+let.a) .c:
    print(let.a, let.b, let.c)

# output 1 2 3
1
répondu guramarx 2018-05-08 05:32:01

aussi longtemps que exec() (et eval()) est autorisé à l'intérieur de lambda, vous pouvez faire les assignations à l'intérieur de lambda:

q = 3

def assign(var_str, val_str):
    exec("global " + var_str + "; " + 
    var_str + " = " + val_str)

lambda_assign = lambda var_str, val_str: assign(var_str, val_str)

q ## gives: 3

lambda_assign("q", "100")

q ## gives: 100

## what would such expression be a win over the direct:

q = 100

## ? `lambda_assign("q", "100")` will be for sure slower than
##   `q = 100` isn't it?

q_assign = lambda v: assign("q", v)

q_assign("33")

q ## 33

## but do I need lambda for q_assign?

def q_assign(v): assign("q", v) 

## would do it, too, isn't it?

mais puisque les expressions lambda ne permettent de définir qu'une seule expression à l'intérieur de leur corps (du moins en Python ...), ce qui serait le point de permettre une affectation à l'intérieur d'un lambda? Son effet net serait d'affecter directement (sans utiliser de lambda) q = 100, n'est-ce pas?

ce serait encore plus rapide que de le faire sur un lambda, puisque vous avez au moins une fonction de recherche et d'exécution de moins à exécuter ...

1
répondu Gwang-Jin Kim 2018-05-12 08:24:44

en l'état actuel, Python a été conçu comme un langage basé sur des énoncés. Par conséquent, les assignations et autres reliures de noms sont des énoncés et n'ont aucun résultat.

les développeurs de Python core discutent actuellement de PEP 572, qui introduirait un nom-binding expression.

0
répondu holdenweb 2018-04-29 20:19:49

je pense que tous les gars ont déjà répondu à cela. Nous utilisons surtout la fonction lambdas quand nous voulons:

- créer quelques fonctions simples qui font le travail parfaitement dans un endroit spécifique(la plupart du temps caché à l'intérieur d'autres grandes fonctions - La fonction lambda n'a pas de nom -Peut être utilisé avec d'autres fonctions intégrées telles que map, list et ainsi de suite ...

>>> Celsius = [39.2, 36.5, 37.3, 37.8] 
>>> Fahrenheit = map(lambda x: (float(9)/5)*x + 32, Celsius) # mapping the list here  
>>> print Fahrenheit
[102.56, 97.700000000000003, 99.140000000000001, 100.03999999999999]

veuillez visiter cette page Web , cela pourrait être utile.Keep it up !!! https://www.python-course.eu/lambda.php

0
répondu Jonas Amara 2018-05-10 09:34:06