2010-05-24 18 views
5

je remarquai un problème quand je cherchais à utiliser dans un del lambda pour amincir une liste de threads à seulement ceux en cours d'exécution:Python del() built-in ne peut pas être utilisé dans l'affectation?

map(lambda x: del(x) if not x.isAlive() else x, self.threads) 

Ignore pour une seconde que cela ne fait rien, je suis juste duper autour de la carte, réduire, et lambda.

Ceci échoue avec une erreur de syntaxe à del (x). Avec un peu de déconner, je pense que le problème est del() ne renvoie pas une valeur. Par exemple, cela ne fonctionne pas avec la même erreur:

b = 5 
x = del(b) 

Cela ne permet cependant pas:

def rmThis(x): del(x) 

Ce qui signifie que j'utilise cette solution de contournement:

map(lambda x: rmThis(x) if not x.isAlive() else x, self.threads) 

Ainsi est le limitation juste parce que del() ne renvoie pas une valeur? Pourquoi pas?

J'utilise python 2.6.2

+0

Est-il nécessaire d'appeler 'del' sur les objets thread explicitement? Si vous pouvez le laisser au compteur de référence ou au garbage collector, vous pouvez écrire à la place: '[thread pour thread dans self.threads si thread.isAlive()]'. –

+3

Même si cela fonctionnait, cela ne fonctionnerait pas :) Vous ne pouvez pas supprimer des éléments d'un itérable pendant que vous l'itérez. –

Répondre

9

Deux problèmes. Le premier est plus subtil, donc je vais d'abord expliquer ça.

Le problème est que del supprime une liaison de variable. Passer une valeur ne servira pas votre objectif.

est ici une illustration

>>> a = 5 
>>> del(a) 
>>> a 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'a' is not defined 
>>> def mydel(x): del(x) 
... 
>>> a = 5 
>>> mydel(a) 
>>> a 
5 
>>> 

Comme vous pouvez le voir. Dans le premier cas, la variable a a été supprimée de l'espace de noms actuel. Il n'y a aucun moyen de se référer à l'objet sur lequel il pointe (en supposant que rien d'autre ne pointe vers la même chose).

Dans le deuxième cas, vous ne supprimez pas a de l'espace de noms. Vous supprimez la liaison de x dans l'espace de nom de la fonction, ce qui fait que vous ne pourrez plus utiliser x comme valeur dans la fonction (c'est-à-dire que c'est une variable indéfinie).

Le deuxième problème est le SyntaxError qui est plus simple. Les fonctions Python lambda ne peuvent contenir que des expressions et non des instructions. del dans pas une expression (c.-à-d., pas un appel de fonction) - c'est une déclaration (le del_stmt) et donc il ne peut pas apparaître dans le corps du lambda. Vous verriez le même problème si vous avez essayé de mettre un print dans le corps du lambda.

>>> lambda x: print x 
    File "<stdin>", line 1 
    lambda x: print x 
       ^
SyntaxError: invalid syntax 

Cela explique également pourquoi le x=del(a) échoue. La syntaxe de l'instruction est invalide. Ce n'est pas une fonction qui peut être appelée.

9

La limitation est que del is a statement et non une expression . Il ne renvoie pas de valeur car les instructions ne renvoient pas de valeurs dans Python.

La forme lambda ne vous permet de mentionner les expressions (parce qu'il ya une return implicite avant l'expression), tandis que la forme def permet à une seule fonction de l'instruction à spécifier sur une ligne (comme vous l'avez fait avec rmThis).

Normalement del est utilisé sans parenthèses, comme:

del x 

Cependant, y compris des parenthèses autour de l'argument comme del(x) est autorisé, mais ne signifie pas qu'il est un appel de fonction.

+1

Ce lien est ce dont j'avais besoin, merci. – emcee

+0

+1 pour le lien. –