underscore for assignment python naming-conventions underscores double-underscore

for - python underscore



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

¿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, ¿el 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 programadores 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) 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.

Y una advertencia de la misma página:

La manipulación de nombres está pensada para dar a las clases una forma fácil de definir variables y métodos de instancia "privados", sin tener que preocuparse por las variables de instancia definidas por clases derivadas, o mezclarse 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 "<stdin>", line 1, in <module> AttributeError: myClass instance has no attribute ''__superprivate'' >>> print mc._semiprivate , world! >>> print mc.__dict__ {''_MyClass__superprivate'': ''Hello'', ''_semiprivate'': '', world!''}


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 configuración regional. 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.


Aquí hay un ejemplo ilustrativo simple sobre cómo las propiedades de subrayado doble 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 sorprendió en un entorno mucho más complejo.


Dado que tanta gente se refiere a la charla de Raymond, solo lo haré un poco más fácil 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 todavía debería estar usando Circle.perimeter para el cálculo, pero en realidad está usando Tire.perimeter , que no es el comportamiento deseado. Es por eso que necesitamos una referencia local en Circle.

Pero ¿ __perimeter qué __perimeter lugar de _perimeter ? Debido a que _perimeter aún 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 padre 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 la invalidación del método no rompe nada, entonces simplemente no necesita __double_leading_underscore .


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 completamente 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, here 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).


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 mutilados 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.


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 como duplicada con esta, 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 mangled 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 import *), ni los nombres se muestran en la ayuda (módulo).


._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

Todavía puede acceder a las variables .__mangled si lo desea desesperadamente. El doble subraya simplemente los nombres de los nombres de los nombres de la variable a algo así 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 "<stdin>", line 1, in <module> 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


__foo__ : esto es solo una convención, una manera para que el sistema Python use nombres que no entren en conflicto con los nombres de los usuarios.

_foo : esto es solo una convención, una forma para que el programador 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 Python.

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


Subrayado (_) en Python

Los siguientes son diferentes lugares donde se usa _ en Python:

Un solo guión bajo

  • En intérprete
  • Despues de un nombre
  • Antes de un nombre

Doble guión bajo:

  • __leading_double_underscore

  • antes después

  • Solo subrayado

En intérprete:

_ devuelve el valor del último valor de expresión ejecutada en Python REPL

>>> a = 10 >>> b = 10 >>> _ Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name ''_'' is not defined >>> a+b 20 >>> _ 20 >>> _ * 2 40 >>> _ 40 >>> _ / 2 20

Para ignorar valores:

Varias veces no queremos que los valores de retorno en ese momento asignen esos valores a wnderscore. Se utiliza como variable desechable.

# Ignore a value of specific location/index for _ in rang(10) print "Test" # Ignore a value when unpacking a,b,_,_ = my_method(var1)

Despues de un nombre

Python tiene sus palabras clave predeterminadas que no podemos usar como nombre de variable. Para evitar este conflicto entre la palabra clave de python y la variable, usamos el guión bajo después del nombre

Ejemplo:

>>> class MyClass(): ... def __init__(self): ... print "OWK" >>> def my_defination(var1 = 1, class_ = MyClass): ... print var1 ... print class_ >>> my_defination() 1 __main__.MyClass >>>

Antes de un nombre

El guión bajo antes del nombre de la variable / función / método indica al programador que es solo para uso interno, que se puede modificar cuando la clase lo desee.

Aquí el prefijo de nombre por el guión bajo se trata como no público. Si especifica desde Import *, todo el nombre comienza con _ no se importará.

Python no especifica verdaderamente privado, por lo que estos pueden llamarse directamente desde otros módulos si está especificado en todos . También lo llamamos débil Privado

class Prefix: ... def __init__(self): ... self.public = 10 ... self._private = 12 >>> test = Prefix() >>> test.public 10 >>> test._private 12 Python class_file.py def public_api(): print "public api" def _private_api(): print "private api"

Llamando archivo desde REPL

>>> from class_file import * >>> public_api() public api >>> _private_api() Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name ''_private_api'' is not defined >>> import class_file >>> class_file.public_api() public api >>> class_file._private_api() private api Double Underscore(__)

__leading_double_underscore

El guión bajo doble indica al intérprete de Python que reescriba el nombre para evitar conflictos en la subclase. El intérprete cambia el nombre de la variable con la extensión de la clase y esa característica conocida como Mangling. testFile.py

class Myclass(): def __init__(self): self.__variable = 10

Llamando desde REPL

>>> import testFile >>> obj = testFile.Myclass() >>> obj.__variable Traceback (most recent call last): File "", line 1, in AttributeError: Myclass instance has no attribute ''__variable'' nce has no attribute ''Myclass'' >>> obj._Myclass__variable 10

En Mangling python interpreter modifica el nombre de la variable con ___. Por lo tanto, se usa como miembro privado porque otra clase no puede acceder a esa variable directamente. El propósito principal de __ es usar variables / métodos solo en clase. Si desea usarlo fuera de la clase, puede hacer una API pública.

class Myclass(): def __init__(self): self.__variable = 10 def func(self) print self.__variable

Llamando desde REPL

>>> import testFile >>> obj = testFile.Myclass() >>> obj.func() 10

__ANTES DESPUÉS__

Nombre con inicio con __ y finaliza con los mismos métodos especiales en Python. Python proporciona estos métodos para utilizarlo como sobrecarga del operador según el usuario.

Python proporciona esta convención para diferenciar entre la función definida por el usuario con la función del módulo

class Myclass(): def __add__(self,a,b): print a*b

Llamando desde REPL

>>> import testFile >>> obj = testFile.Myclass() >>> obj.__add__(1,2) 2 >>> obj.__add__(5,2) 10

Reference


Un solo 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 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 .