¿Por qué algunas funciones tienen guiones bajos “__” antes y después del nombre de la función?

Esto parece ocurrir mucho, y se preguntaba si esto era un requisito en el lenguaje Python, o simplemente una cuestión de convención.

Además, ¿podría alguien nombrar y explicar qué funciones tienden a tener guiones bajos y por qué ( __init__ , por ejemplo)?

De Python PEP 8 – Guía de estilo para el código de Python :

Descriptivo: Estilos de nombres

Se reconocen los siguientes formularios especiales que utilizan guiones bajos o anteriores (generalmente se pueden combinar con cualquier convención de caso):

  • _single_leading_underscore : _single_leading_underscore débil de “uso interno”. Por ejemplo, from M import * no se importan objetos cuyo nombre comience con un guión bajo.

  • single_trailing_underscore_ : utilizado por la convención para evitar conflictos con la palabra clave Python, por ejemplo

    Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore : al nombrar un atributo de clase, invoca la manipulación de nombres (dentro de la clase FooBar, __boo convierte en _FooBar__boo ; ver más abajo).

  • __double_leading_and_trailing_underscore__ : objetos o atributos “mágicos” que viven en espacios de nombres controlados por el usuario. Por __init__ , __init__ , __import__ o __file__ . Nunca inventes tales nombres; Utilícelos únicamente como se documenta.

Tenga en cuenta que los nombres con guiones bajos iniciales y finales están esencialmente reservados para Python: “Nunca invente dichos nombres; utilícelos como está documentado”.

Los otros encuestados son correctos al describir los guiones bajos iniciales y finales como una convención de denominación para los métodos “especiales” o “mágicos”.

Si bien puede llamar a estos métodos directamente ( [10, 20].__len__() por ejemplo), la presencia de los guiones bajos es un indicio de que se pretende invocar estos métodos de manera indirecta ( len([10, 20]) por ejemplo) . La mayoría de los operadores de Python tienen un método “mágico” asociado (por ejemplo, a[x] es la forma habitual de invocar a.__getitem__(x) ).

Los nombres rodeados por guiones bajos son “especiales” para Python. Se enumeran en la referencia del lenguaje Python, sección 3, “Modelo de datos” .

En realidad, uso _ nombres de métodos cuando necesito diferenciar entre nombres de clase padre e hijo. He leído algunos códigos que utilizan esta forma de crear clases de padres e hijos. Como ejemplo puedo proporcionar este código:

 class ThreadableMixin: def start_worker(self): threading.Thread(target=self.worker).start() def worker(self): try: self._worker() except tornado.web.HTTPError, e: self.set_status(e.status_code) except: logging.error("_worker problem", exc_info=True) self.set_status(500) tornado.ioloop.IOLoop.instance().add_callback(self.async_callback(self.results)) 

y el niño que tiene un método _worker

 class Handler(tornado.web.RequestHandler, ThreadableMixin): def _worker(self): self.res = self.render_string("template.html", title = _("Title"), data = self.application.db.query("select ... where object_id=%s", self.object_id) ) 

Esta convención se utiliza para variables o métodos especiales (el llamado “método mágico”) como__init__, len . Estos métodos proporcionan características sintácticas especiales o hacen cosas especiales.

Por ejemplo, archivo indica la ubicación del archivo Python, eq se ejecuta cuando se excuye una expresión == b.

Un usuario, por supuesto, puede crear un método especial personalizado, es un caso muy raro, pero a menudo puede modificar algunos métodos especiales incorporados. (Por ejemplo, debe inicializar la clase con init que se ejecutará al principio cuando se cree una instancia de clase).

  class A: def __init__(self, a): # use special method '__init__' for initializing self.a = a def __custom__(self): # custom special method. you might almost do not use it pass 

Detrás doble subrayado posterior (Nombre Mangling) / De los documentos de Python

Cualquier identificador de la forma __spam (al menos dos guiones bajos, a lo más un guión bajo) se reemplaza textualmente con _classname__spam, donde nombre de clase es el nombre de la clase actual con el subrayado (s) principal (s) eliminado (s). Esta modificación se realiza sin tener en cuenta la posición sintáctica del identificador, por lo que puede utilizarse para definir instancias de clase privada y variables de clase, métodos, variables almacenadas en variables globales e incluso variables almacenadas en instancias. Privado a esta clase en instancias de otras clases.

La manipulación de nombres está destinada a dar a las clases una forma fácil de definir las variables y los métodos de instancia “privados”, sin tener que preocuparse por las variables de instancia definidas por las clases derivadas, o la eliminación con variables de instancia por código fuera de la clase. Tenga en cuenta que las reglas de mutilación están diseñadas principalmente para evitar accidentes; todavía es posible para un alma determinada acceder o modificar una variable que se considera privada.