¿Cuál es el significado de un subrayado simple y doble antes del nombre de un objeto?

¿Puede alguien explicar el significado exacto de tener guiones bajos antes del nombre de un objeto en Python? Además, explica la diferencia entre un guión bajo simple y uno doble. Además, ¿ese significado sigue siendo el mismo si el objeto en cuestión es una variable, una función, un método, etc.?

Solo subrayado

Los nombres, en una clase, con un guión bajo, son simplemente para indicar a otros progtwigdores que el atributo o método pretende ser privado. Sin embargo, no se hace nada especial con el nombre en sí.

Para citar PEP-8 :

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

Doble guión bajo (Nombre Mangling)

De los documentos de Python :

Cualquier identificador de la forma __spam (al menos dos guiones bajos, a lo sumo un guión bajo) se reemplaza textualmente con _classname__spam , donde nombre de classname es el nombre de la clase actual con el subrayado (s) destacado (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.

Y una advertencia de la misma página:

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.

Ejemplo

 >>> class MyClass(): ... def __init__(self): ... self.__superprivate = "Hello" ... self._semiprivate = ", world!" ... >>> mc = MyClass() >>> print mc.__superprivate Traceback (most recent call last): File "", line 1, in  AttributeError: myClass instance has no attribute '__superprivate' >>> print mc._semiprivate , world! >>> print mc.__dict__ {'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'} 

Excelentes respuestas hasta ahora, pero faltan algunos cositas. Un solo guión bajo no es exactamente una convención: si usa from foobar import * , y el módulo foobar no define una lista __all__ , los nombres importados del módulo no incluyen aquellos con un guión bajo. Digamos que es principalmente una convención, ya que este caso es un rincón bastante oscuro ;-).

La convención de subrayado principal se usa ampliamente no solo para nombres privados , sino también para lo que C ++ llamaría nombres protegidos , por ejemplo, nombres de métodos que están totalmente destinados a ser reemplazados por subclases (incluso aquellos que tienen que ser reemplazados desde la clase base que raise NotImplementedError ! -) a menudo son nombres de guiones bajos que indican un código que utiliza instancias de esa clase (o subclases) que dichos métodos no deben llamarse directamente.

Por ejemplo, para hacer una cola segura para subprocesos con una disciplina de cola diferente a FIFO, uno importa Cola, subclases Queue.Queue y reemplaza métodos como _get y _put ; “código de cliente” nunca llama a esos métodos (“enganche”), sino a métodos públicos (“organizados”) como put y get (esto se conoce como el patrón de diseño del Método de plantilla ; consulte, por ejemplo, aquí una presentación interesante basada en un video de una charla mía sobre el tema, con la adición de sinopsis de la transcripción).

__foo__ : esto es solo una convención, una forma en que el sistema Python usa nombres que no entrarán en conflicto con los nombres de usuario.

_foo : esto es solo una convención, una forma para que el progtwigdor indique que la variable es privada (lo que sea que signifique en Python).

__foo : esto tiene un significado real: el intérprete reemplaza este nombre con _classname__foo como una forma de garantizar que el nombre no se superponga con un nombre similar en otra clase.

Ninguna otra forma de guiones bajos tiene significado en el mundo de Python.

No hay diferencia entre clase, variable, global, etc. en estas convenciones.

._variable es semiprivada y solo para convenciones

.__variable menudo se considera incorrectamente superprivada, mientras que su significado real es simplemente ponerle nombre a un ángulo para evitar el acceso accidental [1]

.__variable__ se suele reservar para métodos incorporados o variables

Aún puede acceder a las variables .__mangled si lo desea desesperadamente. El doble subraya simplemente los nombres de los nombres de las variables, o los renombra, a algo como instance._className__mangled

Ejemplo:

 class Test(object): def __init__(self): self.__a = 'a' self._b = 'b' >>> t = Test() >>> t._b 'b' 

t._b es accesible porque solo está oculto por convención

 >>> t.__a Traceback (most recent call last): File "", line 1, in  AttributeError: 'Test' object has no attribute '__a' 

t .__ a no se encuentra porque ya no existe debido a la identificación de nombres

 >>> t._Test__a 'a' 

Al acceder a instance._className__variable lugar de solo el doble subrayado, puede acceder al valor oculto

Un guión bajo al principio:

Python no tiene métodos privados reales. En cambio, un subrayado al inicio de un método o nombre de atributo significa que no debe acceder a este método, porque no es parte de la API.

 class BaseForm(StrAndUnicode): def _get_errors(self): "Returns an ErrorDict for the data provided for the form" if self._errors is None: self.full_clean() return self._errors errors = property(_get_errors) 

(Este fragmento de código se tomó del código fuente de django: django / forms / forms.py). En este código, los errors son una propiedad pública, pero el método al que llama esta propiedad, _get_errors, es “privado”, por lo que no debe acceder a ella.

Dos guiones bajos al principio:

Esto causa mucha confusión. No debe utilizarse para crear un método privado. Debería usarse para evitar que su método sea anulado por una subclase o accedido accidentalmente. Veamos un ejemplo:

 class A(object): def __test(self): print "I'm a test method in class A" def test(self): self.__test() a = A() a.test() # a.__test() # This fails with an AttributeError a._A__test() # Works! We can access the mangled name directly! 

Salida:

 $ python test.py I'm test method in class A I'm test method in class A 

Ahora cree una subclase B y personalice para el método __test

 class B(A): def __test(self): print "I'm test method in class B" b = B() b.test() 

La salida será ….

 $ python test.py I'm test method in class A 

Como hemos visto, A.test () no llamó a los métodos B .__ test (), como podríamos esperar. Pero, de hecho, este es el comportamiento correcto para __. Los dos métodos llamados __test () son renombrados automáticamente (modificados) a _A__test () y _B__test (), por lo que no se anulan accidentalmente. Cuando creas un método que comienza con __, significa que no quieres que nadie pueda anularlo, y solo tienes la intención de acceder a él desde dentro de su propia clase.

Dos guiones bajos al principio y al final:

Cuando veamos un método como __this__ , no lo llamemos. Este es un método que Python debe llamar, no tú. Vamos a ver:

 >>> name = "test string" >>> name.__len__() 11 >>> len(name) 11 >>> number = 10 >>> number.__add__(40) 50 >>> number + 50 60 

Siempre hay un operador o función nativa que llama a estos métodos mágicos. A veces es solo un gancho de llamadas de python en situaciones específicas. Por ejemplo, se __init__() cuando el objeto se crea después de __new__() para crear la instancia …

Tomemos un ejemplo …

 class FalseCalculator(object): def __init__(self, number): self.number = number def __add__(self, number): return self.number - number def __sub__(self, number): return self.number + number number = FalseCalculator(20) print number + 10 # 10 print number - 20 # 40 

Para más detalles, vea la guía PEP-8 . Para más métodos mágicos, vea este PDF .

A veces tienes lo que parece ser una tupla con un guión bajo como en

 def foo(bar): return _('my_' + bar) 

En este caso, lo que sucede es que _ () es un alias para una función de localización que opera en un texto para colocarlo en el idioma adecuado, etc., según la ubicación. Por ejemplo, Sphinx hace esto, y encontrarás entre las importaciones.

 from sphinx.locale import l_, _ 

y en sphinx.locale, _ () se asigna como un alias de alguna función de localización.

Si uno realmente quiere hacer una variable de solo lectura, en mi humilde opinión, la mejor manera sería usar property () con solo getter. Con la propiedad () podemos tener control completo sobre los datos.

 class PrivateVarC(object): def get_x(self): pass def set_x(self, val): pass rwvar = property(get_p, set_p) ronly = property(get_p) 

Entiendo que OP hizo una pregunta un poco diferente, pero como encontré otra pregunta que preguntaba por “cómo establecer variables privadas” marcada con este duplicado, pensé en agregar esta información adicional aquí.

Solo guiones bajos es una convención. no hay diferencia desde el punto de vista del intérprete si los nombres comienzan con un solo guión bajo o no.

Los guiones bajos __init__ y finales se utilizan para los métodos __init__ , como __init__ , __bool__ , etc.

Los guiones bajos dobles sin contrapartes también son una convención, sin embargo, los métodos de clase serán manipulados por el intérprete. Para variables o nombres de funciones básicas no existe diferencia.

Tu pregunta es buena, no se trata solo de métodos. Las funciones y los objetos en los módulos también suelen tener un guión bajo, y pueden ser prefijados por dos.

Pero, por ejemplo, los nombres de __double_underscore no se dividen en nombres en los módulos. Lo que sucede es que los nombres que comienzan con uno (o más) guiones bajos no se importan si se importan todos desde un módulo (desde el módulo importación *), ni los nombres se muestran en la ayuda (módulo).

Aquí hay un ejemplo ilustrativo simple sobre cómo las propiedades de doble guión bajo pueden afectar a una clase heredada. Así que con la siguiente configuración:

 class parent(object): __default = "parent" def __init__(self, name=None): self.default = name or self.__default @property def default(self): return self.__default @default.setter def default(self, value): self.__default = value class child(parent): __default = "child" 

Si luego creas una instancia secundaria en el REPL de python, verás lo siguiente

 child_a = child() child_a.default # 'parent' child_a._child__default # 'child' child_a._parent__default # 'parent' child_b = child("orphan") ## this will show child_b.default # 'orphan' child_a._child__default # 'child' child_a._parent__default # 'orphan' 

Esto puede ser obvio para algunos, pero me tomó desprevenido en un entorno mucho más complejo

Las variables de instancia “privadas” a las que no se puede acceder, excepto desde dentro de un objeto, no existen en Python. Sin embargo, hay una convención seguida por la mayoría del código de Python: un nombre con un guión bajo (p. Ej. _Spam) debe tratarse como una parte no pública de la API (ya sea una función, un método o un miembro de datos) . Debe considerarse un detalle de implementación y sujeto a cambios sin previo aviso.

referencia https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references

Obtener los datos de _ y __ es bastante fácil; Las otras respuestas las expresan bastante bien. El uso es mucho más difícil de determinar.

Así es como lo veo:

 _ 

Debe utilizarse para indicar que una función no es para uso público como, por ejemplo, una API. Esto y la restricción de importación hacen que se comporte de manera muy parecida a la internal en c #.

 __ 

Se debe utilizar para evitar la colisión de nombres en la jerarquía hereditaria y para evitar la vinculación tardía. Al igual que privado en c #.

==>

Si desea indicar que algo no es para uso público, debe actuar como uso protected _ . Si desea indicar que algo no es para uso público, debe actuar como uso private __ .

Esta es también una cita que me gusta mucho:

El problema es que el autor de una clase puede pensar legítimamente “este nombre de atributo / método debe ser privado, solo accesible desde esta definición de clase” y usar la convención __private. Pero más adelante, un usuario de esa clase puede hacer una subclase que legítimamente necesita acceso a ese nombre. Entonces, o bien la superclase tiene que ser modificada (lo que puede ser difícil o imposible), o el código de la subclase tiene que usar nombres manipulados manualmente (lo que es feo y, en el mejor de los casos, frágil).

Pero el problema con eso es, en mi opinión, que si no hay un IDE que le avise cuando invalide los métodos, encontrar el error podría llevarle un tiempo si ha anulado accidentalmente un método de una clase base.

Ya que tanta gente se refiere a la charla de Raymond, solo lo facilitaré un poco escribiendo lo que dijo:

La intención de los dobles guiones no fue sobre la privacidad. La intención era usarlo exactamente así.

 class Circle(object): def __init__(self, radius): self.radius = radius def area(self): p = self.__perimeter() r = p / math.pi / 2.0 return math.pi * r ** 2.0 def perimeter(self): return 2.0 * math.pi * self.radius __perimeter = perimeter # local reference class Tire(Circle): def perimeter(self): return Circle.perimeter(self) * 1.25 

En realidad, es lo opuesto a la privacidad, se trata de libertad. Hace que sus subclases sean libres de anular cualquier método sin romper los otros .

Digamos que no mantienes una referencia local de perimeter en Circle . Ahora, un Tire clase derivada anula la implementación del perimeter , sin tocar el area . Cuando llama a Tire(5).area() , en teoría aún debería estar usando Circle.perimeter para el cálculo, pero en realidad está usando Tire.perimeter , que no es el comportamiento deseado. Por eso necesitamos una referencia local en Circle.

Pero ¿ __perimeter qué __perimeter lugar de _perimeter ? Debido a que _perimeter todavía le da a la clase derivada la oportunidad de anular:

 class Tire(Circle): def perimeter(self): return Circle.perimeter(self) * 1.25 _perimeter = perimeter 

El doble guión bajo tiene denominación de nombres, por lo que hay muy pocas posibilidades de que la referencia local en la clase principal se anule en la clase derivada. por lo tanto, ” hace que sus subclases sean libres de anular cualquier método sin romper los otros “.

Si su clase no se heredará, o el reemplazo de método no rompe nada, entonces simplemente no necesita __double_leading_underscore .

Excelentes respuestas y todas son correctas. He proporcionado un ejemplo simple junto con una definición / significado simple.

Sentido:

some_variable –► es público cualquiera puede ver esto.

_some_variable –► es público, cualquiera puede ver esto, pero es una convención para indicar privado … advirtiendo que Python no hace cumplir nada.

__some_varaible –► Python reemplaza el nombre de la variable con _classname__some_varaible (nombre AKA) y reduce / oculta su visibilidad y se parece más a una variable privada.

Solo para ser honesto aquí De acuerdo con la documentación de Python

Las variables de instancia “privadas” a las que no se puede acceder, excepto desde dentro de un objeto no existen en Python ”

El ejemplo:

 class A(): here="abc" _here="_abc" __here="__abc" aObject=A() print(aObject.here) print(aObject._here) # now if we try to print __here then it will fail because it's not public variable #print(aObject.__here)