¿Cuándo es útil en python?

Realmente no puedo pensar en ninguna razón por la que Python necesite la palabra clave del (y la mayoría de los idiomas parecen no tener una palabra clave similar). Por ejemplo, en lugar de eliminar una variable, uno podría asignarle None . Y al eliminar de un diccionario, se podría agregar un método del .

¿Hay alguna razón para mantener del en Python, o es un vestigio de los días de recolección de basura de Python?

En primer lugar, puedes deleitarte de otras cosas además de variables locales

 del list_item[4] del dictionary["alpha"] 

Ambos deberían ser claramente útiles. En segundo lugar, el uso de del en una variable local aclara la intención. Comparar:

 del foo 

a

 foo = None 

Sé que en el caso de del foo la intención es eliminar la variable del scope. No está claro que foo = None esté haciendo eso. Si alguien acaba de asignar foo = None , podría pensar que era un código muerto. Pero al instante sé lo que intentaba hacer alguien que codifica a del foo .

Hay una parte de lo que hace (de la referencia del lenguaje Python ):

La eliminación de un nombre elimina el enlace de ese nombre del espacio de nombres local o global

La asignación de None a un nombre no elimina el enlace del nombre del espacio de nombres.

(Supongo que podría haber algún debate sobre si eliminar un enlace de nombre es realmente útil , pero esa es otra pregunta).

Un lugar que he encontrado del útil es la limpieza de variables extrañas en los bucles:

 for x in some_list: do(x) del x 

Ahora puede estar seguro de que x no estará definido si lo usa fuera del bucle for.

Hay un ejemplo específico de cuándo debería usar del (puede haber otros, pero conozco este caso) cuando esté usando sys.exc_info() para inspeccionar una excepción. Esta función devuelve una tupla, el tipo de excepción que se generó, el mensaje y un rastreo.

Los primeros dos valores suelen ser suficientes para diagnosticar un error y actuar sobre él, pero el tercero contiene la stack de llamadas completa entre el lugar donde se generó la excepción y el lugar donde se captura la excepción. En particular, si haces algo como

 try: do_evil() except: exc_type, exc_value, tb = sys.exc_info() if something(exc_value): raise 

En el rastreo, tb termina en los locales de la stack de llamadas, creando una referencia circular que no puede ser recogida de basura. Por lo tanto, es importante hacer:

 try: do_evil() except: exc_type, exc_value, tb = sys.exc_info() del tb if something(exc_value): raise 

Para romper la referencia circular. En muchos casos en los que desearía llamar a sys.exc_info() , como con metaclass magic, el rastreo es útil, por lo que debe asegurarse de limpiarlo antes de poder dejar el controlador de excepciones. Si no necesita el rastreo, debe eliminarlo inmediatamente o simplemente haga lo siguiente:

 exc_type, exc_value = sys.exc_info()[:2] 

Para evitarlo todo junto.

Sólo otro pensamiento.

Al depurar aplicaciones http en un marco como Django, la stack de llamadas llena de variables inútiles y desordenadas usadas previamente, especialmente cuando es una lista muy larga, podría ser muy dolorosa para los desarrolladores. por lo tanto, en este punto, el control del espacio de nombres podría ser útil.

Eliminar una variable es diferente a configurarlo en Ninguno

Eliminar nombres de variables con del es probablemente algo que se usa raramente, pero es algo que no podría lograrse de manera trivial sin una palabra clave. Si puedes crear un nombre de variable escribiendo a=1 , es bueno que teóricamente puedas deshacer esto eliminando a.

Puede hacer que la depuración sea más fácil en algunos casos, ya que intentar acceder a una variable eliminada generará un error de nombre.

Puede eliminar atributos de instancia de clase

Python te permite escribir algo como:

 class A(object): def set_a(self, a): self.a=a a=A() a.set_a(3) if hasattr(a, "a"): print("Hallo") 

Si elige agregar atributos dinámicamente a una instancia de clase, ciertamente desea poder deshacerlos escribiendo

 del aa 

Usar “del” explícitamente también es una mejor práctica que asignar una variable a Ninguna. Si intentas eliminar una variable que no existe, obtendrás un error de tiempo de ejecución, pero si intentas establecer una variable que no existe en Ninguno, Python establecerá una nueva variable en Ninguno, dejando la variable que quería borrado donde estaba. Así que del te ayudará a atrapar tus errores antes

Para agregar algunos puntos a las respuestas anteriores: del x

La definición de x indica r -> o (una referencia r apunta a un objeto o ) pero del x cambia r lugar de o . Es una operación en la referencia (puntero) a objeto en lugar del objeto asociado con x . La distinción entre r y o es clave aquí.

  • Lo elimina de los locals() .
  • Elimina de globals() si x pertenece allí.
  • Elimina del marco de la stack (elimina la referencia físicamente de él, pero el objeto reside en el conjunto de objetos y no en el marco de la stack).
  • Se elimina del ámbito actual. Es muy útil limitar el scope de la definición de una variable local, que de lo contrario puede causar problemas.
  • Es más sobre la statement del nombre en lugar de la definición de contenido.
  • Afecta a donde pertenece x , no a donde x apunta. El único cambio físico en la memoria es este. Por ejemplo, si x está en un diccionario o lista, se elimina (como referencia) de allí (y no necesariamente de la agrupación de objetos). En este ejemplo, el diccionario al que pertenece es el marco de stack ( locals() ), que se superpone con globals() .

Forzar el cierre de un archivo después de usar numpy.load:

Un uso de nicho tal vez, pero lo encontré útil cuando uso numpy.load para leer un archivo. De vez en cuando actualizaría el archivo y necesitaría copiar un archivo con el mismo nombre en el directorio.

Usé del para liberar el archivo y permitirme copiar en el nuevo archivo.

Tenga en cuenta que quiero evitar el administrador de contexto ya que estaba jugando con los gráficos en la línea de comandos y no quería presionar la pestaña mucho.

Vea esta pregunta.

del se ve a menudo en los archivos __init__.py . Cualquier variable global que se define en un archivo __init__.py se “exporta” automáticamente (se incluirá en una from module import * ). Una forma de evitar esto es definir __all__ , pero esto puede __all__ y no todos lo usan.

Por ejemplo, si tiene código en __init__.py como

 import sys if sys.version_info < (3,): print("Python 2 not supported") 

Entonces su módulo exportaría el nombre del sistema. En lugar de eso deberías escribir

 import sys if sys.version_info < (3,): print("Python 2 not supported") del sys 

¿Cuándo es útil en python?

Puede usarlo para eliminar un solo elemento de una matriz en lugar de la syntax de segmento x[i:i+1]=[] . Esto puede ser útil si, por ejemplo, está en os.walk y desea eliminar un elemento del directorio. No consideraría una palabra clave útil para esto, ya que uno podría simplemente hacer un método [].remove(index) (el método .remove es en realidad la búsqueda y eliminación de la primera instancia del valor).

Como ejemplo de para qué se puede usar del, me resulta útil en situaciones como esta:

 def f(a, b, c=3): return '{} {} {}'.format(a, b, c) def g(**kwargs): if 'c' in kwargs and kwargs['c'] is None: del kwargs['c'] return f(**kwargs) # g(a=1, b=2, c=None) === '1 2 3' # g(a=1, b=2) === '1 2 3' # g(a=1, b=2, c=4) === '1 2 4' 

Estas dos funciones pueden estar en diferentes paquetes / módulos y el progtwigdor no necesita saber qué valor predeterminado tiene el argumento c en f . Entonces, al utilizar kwargs en combinación con del, puede decir “Quiero el valor predeterminado en c” configurándolo en Ninguno (o, en este caso, también dejarlo).

Podrías hacer lo mismo con algo como:

 def g(a, b, c=None): kwargs = {'a': a, 'b': b} if c is not None: kwargs['c'] = c return f(**kwargs) 

Sin embargo encuentro el ejemplo anterior más SECO y elegante.

Creo que una de las razones por las que del tiene su propia syntax es que reemplazarla con una función puede ser difícil en ciertos casos dado que opera en el enlace o variable y no en el valor al que hace referencia. Por lo tanto, si se creara una versión de la función del del, se debería pasar un contexto. Del foo tendría que convertirse en globals (). Remove (‘foo’) o locals (). Remove (‘foo’) que se complica y menos legible. Todavía digo que deshacerse de del sería bueno dado su uso aparentemente raro. Pero eliminar características / defectos del lenguaje puede ser doloroso. Tal vez Python 4 lo eliminará 🙂

Otro uso más de nicho: en pyroot con ROOT5 o ROOT6, “del” puede ser útil para eliminar un objeto python que se refiera a un objeto C ++ que ya no existe. Esto permite que la búsqueda dinámica de pyroot encuentre un objeto C ++ con nombre idéntico y lo vincule al nombre de python. Para que puedas tener un escenario como:

 import ROOT as R input_file = R.TFile('inputs/___my_file_name___.root') tree = input_file.Get('r') tree.Draw('hy>>hh(10,0,5)') R.gPad.Close() R.hy # shows that hy is still available. It can even be redrawn at this stage. tree.Draw('hy>>hh(3,0,3)') # overwrites the C++ object in ROOT's namespace R.hy # shows that R.hy is None, since the C++ object it pointed to is gone del R.hy R.hy # now finds the new C++ object 

Con suerte, este nicho se cerrará con la gestión más inteligente de objetos de ROOT7.

Una vez tuve que usar:

 del serial serial = None 

porque usando solo:

 serial = None 

no liberó el puerto serie lo suficientemente rápido como para abrirlo de nuevo inmediatamente. De esa lección aprendí que lo que realmente quería decir es: “¡VAYA A CONOCER AHORA! Y espere hasta que termine”, y eso es realmente útil en muchas situaciones. Por supuesto, puede tener un system.gc.del_this_and_wait_balbalbalba(obj) .

del es el equivalente de “unset” en muchos idiomas y como punto de referencia cruzada que se mueve de otro idioma a python. Las personas tienden a buscar comandos que hacen lo mismo que solían hacer en su primer idioma … también configurando una var para “” o ninguna realmente no elimina la var del ámbito … simplemente vacía su valor, el nombre de la var en sí todavía se almacenaría en la memoria … ¿por qué?! en un script intensivo de memoria … mantener la basura detrás de él solo no, no y de todos modos … todos los idiomas tienen alguna forma de función “desarmar / eliminar” var … ¿por qué no python?

Cada objeto en Python tiene un identificador, Tipo, recuento de referencia asociado, cuando usamos el recuento de referencia se reduce, cuando el recuento de referencia se convierte en cero, es un posible candidato para obtener la basura recolectada. Esto diferencia el del cuando se compara con establecer un identificador en Ninguno. En el caso posterior, simplemente significa que el objeto se queda fuera de control (hasta que quedamos fuera del scope, en cuyo caso el recuento se reduce) y simplemente ahora el punto de identificación a algún otro objeto (ubicación de memoria).