51 votes

Est-ce que l'utilisation de del bad?

J'ai souvent utiliser del dans mon code pour supprimer des objets:

>>> array = [4, 6, 7, 'hello', 8]
>>> del(array[array.index('hello')])
>>> array
[4, 6, 7, 8]
>>> 

Mais j'ai entendu beaucoup de gens dire que l'utilisation de l' del est unpythonic. Est l'aide de del mauvaise pratique?

>>> array = [4, 6, 7, 'hello', 8]
>>> array[array.index('hello'):array.index('hello')+1] = ''
>>> array
[4, 6, 7, 8]
>>> 

Si non, pourquoi il y a de nombreuses façons d'accomplir la même chose en python? Est-ce mieux que les autres?

Option 1: à l'aide d' del

>>> arr = [5, 7, 2, 3]
>>> del(arr[1])
>>> arr
[5, 2, 3]
>>> 

Option 2: à l'aide d' list.remove()

>>> arr = [5, 7, 2, 3]
>>> arr.remove(7)
>>> arr
[5, 2, 3]
>>> 

Option 3: utilisation de list.pop()

>>> arr = [5, 7, 2, 3]
>>> arr.pop(1)
7
>>> arr
[5, 2, 3]
>>> 

Option 4: à l'aide de découpage

>>> arr = [5, 7, 2, 3]
>>> arr[1:2] = ''
>>> arr
[5, 2, 3]
>>> 

Je suis désolé si cette question semble être d'avis, mais je suis à la recherche d'une réponse à ma question, et je vais ajouter une prime au bout de 2 jours si je ne reçois pas une réponse appropriée.

Edit:

Car il y a beaucoup de suppléants à l'aide d' del supprimer certaines parties d'objets, l'un facteur unique à gauche de l' del est sa capacité à supprimer des objets totalement:

>>> a = 'hello'
>>> b = a
>>> del(a)
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> b
'hello'
>>> 

Cependant, ce qui est le point de l'aide à la 'destruction' des objets?

Aussi, pourquoi le code suivant modifier les deux variables:

>>> a = []
>>> b = a
>>> a.append(9)
>>> a
[9]
>>> b
[9]
>>> 

Mais l' del déclaration ne permet pas d'obtenir le même effet?

>>> a = []
>>> b = a
>>> del(a)
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> b
[]
>>> 

49voto

Erik Allik Points 9158

Les autres réponses sont à la recherche à partir d'un point de vue technique (c'est à dire quelle est la meilleure façon de modifier une liste), mais je dirais que le (beaucoup) plus importante raison pour laquelle les gens sont ce qui suggère par exemple de découpage, c'est qu'il ne doit pas modifier la liste d'origine.

La raison pour cela est que généralement, la liste est venu de quelque part. Si vous le modifiez, vous pouvez unknowningly cause d'une très mauvaise et difficile à détecter les effets secondaires, qui peuvent causer des bugs ailleurs dans le programme. Ou même si vous n'avez pas à cause d'un bug immédiatement, vous allez rendre votre programme plus difficile à comprendre et à raisonner et à déboguer.

Par exemple, les interprétations de la liste/générateur d'expressions de nice en qui ils n'ont jamais muter la "source" de la liste, ils sont passés:

[x for x in lst if x != "foo"]  # creates a new list
(x for x in lst if x != "foo")  # creates a lazy filtered stream

Bien sûr, cela est souvent plus cher (de mémoire sage), parce qu'il crée une nouvelle liste, mais un programme qui utilise cette approche est mathématiquement plus pure et la plus facile de raisonner sur. Et avec lazy listes (générateurs et générateur d'expressions), même la surcharge de la mémoire disparaît, et les calculs sont exécutés uniquement sur demande; voir http://www.dabeaz.com/generators/ pour passer une excellente introduction. Et vous ne devriez pas trop penser à l'optimisation lors de la conception de votre programme (voir http://programmers.stackexchange.com/questions/80084/is-premature-optimization-really-the-root-of-all-evil). Aussi, la suppression d'un élément d'une liste est assez cher, sauf si c'est une liste chaînée (qui Python list ne l'est pas; pour la liste, voir collections.deque).


En fait, sans effets secondaires fonctions et immuable structures de données sont à la base de la Programmation Fonctionnelle, un très puissant paradigme de programmation.

Toutefois, dans certaines circonstances, il est OK pour modifier une structure de données en place (même en FP, si le langage le permet), comme lorsqu'elle est localement créé un, ou copié à partir de l'entrée de la fonction:

def sorted(lst):
    ret = list(lst)  # make a copy
    # mutate ret
    return ret

- cette fonction semble être une pure fonction de l'extérieur, car il ne modifie pas ses entrées (et aussi ne dépend que de ses arguments et rien d'autre (c'est à dire qu'il n'a pas de (global) de l'état), qui est une autre condition pour que quelque chose soit une Pure Fonction).

Donc, tant que vous savez ce que vous faites, del n est pas mauvais; mais l'utilisation de toute sorte de données de mutation avec une extrême prudence et seulement quand vous avez. Toujours commencer avec un peut de moins en moins efficace, mais plus correct et mathématiquement le code élégant.

...et d'apprendre la Programmation Fonctionnelle :)

P. S. remarque qu' del peut également être utilisé pour supprimer des variables locales et donc d'éliminer les références à des objets en mémoire, ce qui est souvent utile pour quelle que soit la GC à des fins connexes.


La réponse à votre deuxième question:

Quant à la deuxième partie de votre question sur del suppression des objets complètement - ce n'est pas le cas: en fait en Python, il n'est même pas possible de dire à l'interprète/VM pour supprimer un objet de mémoire, parce que Python est l'un des ordures collectées langue (comme Java, C#, Ruby, Haskell, etc) et c'est l'exécution qui décide ce qu'il faut supprimer et quand.

Au lieu de cela, ce del n'lorsqu'il est appelé sur une variable (par opposition à une clé de dictionnaire ou un élément de liste) comme ceci:

del a

c'est qu'il seulement supprime le local (ou global) de la variable et non pas ce que la variable de points (chaque variable en Python est titulaire d'un pointeur/référence à son contenu, pas le contenu lui-même). En fait, depuis que les habitants et les variables globales sont stockés sous forme de dictionnaire sous le capot (voir locals() et globals()), del a est équivalent à:

del locals()['a']

ou del globals()['a'] lorsqu'il est appliqué à une échelle mondiale.

donc, si vous avez:

a = []
b = a

vous faites une liste, enregistrer une référence en a , puis de faire une copie de celui de référence et de les stocker en b sans copier/contact de la liste de l'objet lui-même. Par conséquent, ces deux appels d'affecter un seul et même objet:

a.append(1)
b.append(2)
 # the list will be [1, 2]

alors que la suppression d' b n'est en aucune façon liée à toucher ce qu' b points de:

a = []
b = a
del b
# a is still untouched and points to a list

Aussi, même lorsque vous appelez del sur un attribut de l'objet (par exemple, del self.a), vous êtes toujours en fait de la modification d'un dictionnaire, self.__dict__ juste comme vous êtes en train de modifier locals()/globals() lorsque vous effectuez del a.

P. S. comme Sven Marcnah a souligné que l' del locals()['a'] n'a pas fait de supprimer la variable locale a lorsque l'intérieur d'une fonction, ce qui est correct. Ceci est probablement dû à l' locals() retour une copie du réel habitants. Toutefois, la réponse est toujours valide.

12voto

Hunter Larco Points 513

Python contient de nombreuses façons de supprimer des éléments d'une liste. Tous sont utiles dans différentes situations.

# removes the first index of a list
del arr[0]

# Removes the first element containing integer 8 from a list
arr.remove(8)

# removes index 3 and returns the previous value at index 3
arr.pop(3)

# removes indexes 2 to 10
del arr[2:10]

Ainsi, ils ont tous leur place. Clairement lorsque l'on veut supprimer le numéro 8, par exemple le nombre 2 est une meilleure option que de 1 ou 3. Donc, c'est vraiment ce qui fait sens selon les circonstances et ce qui est le plus logiquement du son.

MODIFIER

La différence entre arr.pop(3) et del arr[3] , c'est que la pop retourne l'élément supprimé. Ainsi, il peut être utile pour transférer les éléments supprimés dans d'autres tableaux ou des structures de données. Sinon, les deux ne diffèrent pas en cours d'utilisation.

10voto

Nan, je ne pense pas que l'aide d' del est mauvais à tous. En fait, il y a des situations où c'est pratiquement la seule option raisonnable, comme la suppression des éléments d'un dictionnaire:

k = {'foo': 1, 'bar': 2}
del k['foo']

Peut-être le problème, c'est que les débutants ne sont pas pleinement comprendre comment les variables en Python, donc l'utilisation (ou l'abus) de l' del peut-être pas familier.

6voto

kojiro Points 24374

L'utilisation de l' del lui-même n'est pas mauvais en soi; cependant, il y a deux aspects qui contribuent à particulier odeurs de code:

  1. C'est un effet secondaire, une partie d'une séquence d'étapes, et n'a pas de sens par lui-même.
  2. Il se peut que l' del se produit dans le code manuel de gestion de la mémoire indicatif d'une mauvaise compréhension de Python de délimitation de l'étendue et de la gestion automatique de la mémoire. De la même manière que l' with déclaration est plus idiomatique pour la manipulation des descripteurs de fichiers que file.close, à l'aide de l'étendue et le contexte est plus idiomatique que manuellement nuking membres.

Mais ce n'est guère canon – si l' del mot-clé ont été vraiment "mauvais", il ne serait pas dans le noyau de la langue. Je suis juste en train de jouer l'Avocat du Diable – pour expliquer pourquoi certains programmeurs peuvent l'appeler "mauvais" et, éventuellement, de vous donner une position à l'encontre de. ;)

2voto

Namey Points 532

Je ne pense pas que j'ai jamais entendu quelqu'un dire qu' del est le mal, du moins pas plus que n'importe quel autre langage. La question entre del et d'autres approches vient vraiment à votre cas d'utilisation. Les cas suivants sont parfaits pour del:

  1. La suppression des variables à partir de votre portée. Pourquoi voudriez-vous faire cela? Imaginez que vous êtes en déclarant un module qui calcule une variable de package, mais que les consommateurs de ce module a jamais besoin d'elle. Alors que vous pourriez créer un tout nouveau module, qui pourrait être exagéré ou pourrait obscurcir ce qui est calculé. Pour un exemple, vous voudrez peut-être le suivant:

    GLOBAL_1 = 'Some arbitrary thing'
    GLOBAL_2 = 'Something else'
    
    def myGlobal3CalculationFunction(str1, str2):
        # Do some transforms that consumers of this module don't need
        return val
    
    GLOBAL_3 = myGlobal3CalculationFunction(GLOBAL_1, GLOBAL_2)
    # Mystery function exits stage left
    del myGlobal3CalculationFunction
    

    Fondamentalement, personne n'est en désaccord avec l'aide d' del supprimer les variables de portée, lorsque cela est nécessaire. La même chose s'applique à des valeurs dans les dictionnaires, ou à peu près tout accessible par un nom ou similaire immuable références (propriétés de la classe, les propriétés de l'occurrence, dict valeurs, etc.).

  2. L'autre cas est celui dans lequel vous voulez supprimer un élément à partir d'une liste ou similaire séquence ordonnée. Qui ne le sont pas vraiment différent de la première fois dans une affaire d'une certaine façon (voir, car ils peuvent tous être accessibles comme clé-valeur des conteneurs, avec des listes de juste arrivé d'avoir de manière fiable-commandé entier touches). Dans tous ces cas, vous êtes dans le même bateau de vouloir supprimer une référence à des données qui existe dans ce cas particulier (puisque même les classes sont une instance de classe). Vous êtes en train de faire une modification.

    N'ayant ordonné et spécial indices que quelque chose est différent pour les listes? La différence fondamentale avec une liste, c'est que de faire une modification rend tous vos anciennes clés fondamentalement inutile, sauf si vous êtes très prudent. Python vous donne la capacité de représenter des données très sémantiquement: plutôt que d'avoir une liste d' [actor, verb, object] et de la cartographie des indices, vous pouvez avoir une belle dict de {'actor' : actor, 'verb' : verb, 'object' : object}. Il y a souvent beaucoup de valeur dans ce genre de ce genre d'accès (c'est pourquoi nous avons des fonctions d'accès par nom, plutôt que par le nombre): si l'ordre n'est pas important, pourquoi le rendre rigide? Si votre commande EST importante, pourquoi êtes-vous gâcher quelque chose qui le rend toutes vos références non valides (c'est à dire, l'élément de positions, la distance entre les éléments).

La question fondamentale est pourquoi vous seriez directement de la suppression d'une liste de valeur par l'indice. Dans la plupart des cas, les opérations qui modifient les éléments de listes de place évident implémentations par d'autres fonctions. Le meurtre d'un élément avec une valeur donnée? Vous remove il. La mise en œuvre d'une file d'attente ou d'une pile? Vous pop il (ne pas verrouiller). La réduction de la ref compter pour une instance dans la liste? l[i] = None fonctionne tout aussi bien, et votre ancien indices pointent toujours à la même chose. Éléments de filtrage? Vous filter ou l'utilisation d'une compréhension de liste. Faire une copie de la liste, moins certains éléments? Vous slice il. Se débarrasser des doublons, hashable éléments? Vous pouvez list(set([])) ou regarde itertools si vous avez juste besoin de parcourir les éléments uniques une fois.

Après à vous débarrasser de tous ces cas, vous vous retrouvez avec environ deux communes de cas d'utilisation pour l'utilisation de del pour une liste. Tout d'abord, vous pouvez supprimer des éléments aléatoires par l'index. Il y a plus que quelques cas où cela pourrait être utile, et del est totalement approprié. Deuxièmement, vous avez stocké des indices qui représentent où vous êtes dans la liste (c'est à dire, la marche d'une pièce à un couloir où vous au hasard de détruire une pièce, parfois, de la Charlie Sheen Style de Programmation Guide). Cela devient difficile si vous avez plus d'un indice pour la même liste, que l'utilisation d' del signifie que tous les indices doivent être ajustés en conséquence. C'est moins fréquent, car les structures que vous marchez à l'aide d'indices sont souvent pas ceux que vous supprimez des éléments (par exemple, de grilles de coordonnées pour un plateau de jeu). Il arrive cependant, comme tout-en boucle sur une liste de sondage d'emplois et suppression de celles qui ont été effectuées.

Cela indique que le problème fondamental avec la suppression d'éléments d'une liste en place par index: vous êtes un peu coincé le faire un à un. Si vous avez les indices de deux éléments à supprimer, puis supprimer le premier? Il ya une bonne chance que votre ancien indice n'a pas de point à ce qu'il était. Les listes sont pour le stockage de l'ordre. Depuis del modifie l'ordre absolu, vous êtes coincé en marchant ou en sautant le long de la liste. Encore une fois, il y a de solides cas d'utilisation (par exemple, au hasard de la destruction), mais il y a des tonnes d'autres cas qui sont tout simplement faux. En particulier parmi les nouveaux Python pour les programmeurs, les gens font des choses horribles avec while boucles sur les fonctions (c'est à dire, en boucle jusqu'à trouver une valeur qui correspond à une entrée, del de l'indice). Del requiert l'un de l'indice de l'entrée, et dès qu'il est exécuté, fait de tous les indices se référant à cette liste, reportez-vous à tout à fait différents de données. Vous pouvez voir où c'est un entretien cauchemar si plusieurs indices sont maintenus. Encore une fois, il n'est pas mauvais. C'est juste que c'est rarement dans la pratique, la meilleure façon de faire les choses avec une liste en Python.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X