¿Cuándo importar nombres al espacio de nombres global? (usando x :: y, desde x import y etc.)

8

He estado programando en varios idiomas durante unos 10 años. Y todavía no he descubierto cuándo es una buena idea importar algo al espacio de nombres global ( using x::yen C ++, from x import yen Python, etc.), por lo que casi nunca lo hago.

Casi siempre me parece una mala idea, aunque solo sea porque limita el conjunto de nombres de variables que puedo usar. Por ejemplo: dónde usarlo using namespace std;o using std::string;en C ++, ya no podría usarlo stringcomo un nombre de variable, lo que ocasionalmente hago (por ejemplo, para funciones de utilidad de cadena).

Pero me pregunto: ¿hay algunas situaciones en las que importar un nombre en el espacio de nombres global realmente tiene sentido? ¿Alguna regla general?

futlib
fuente

Respuestas:

11

En C ++, generalmente está mal visto, especialmente using namespace std. Ese stdespacio de nombres tiene tantos nombres, muchos de los cuales son algoritmos muy genéricos, cuando puede obtener algunas sorpresas extremadamente desagradables using namespace std. Algo así using std::cout;no es tan malo. Pero nunca, nunca, usingnada en el espacio de nombres global en un archivo de encabezado. Eso es un delito de pelotón de fusilamiento.

DeadMG
fuente
1
¿Pero qué hay de mi pregunta? ¿Cuándo usar usando x :: y o importar x desde y?
futlib
4

Deberías hacerlo cuando simplifique tu código. No debe hacerlo cuando causaría conflictos de nomenclatura, o cuando más tarde podría llevarse a ámbitos donde causaría conflictos de nomenclatura, como un archivo de encabezado.

Algunas personas piensan que debería ser raro. Creo que (fuera de los archivos de encabezado) no usarlo debería ser raro, porque el prefijo del espacio de nombres generalmente no agrega ninguna información útil, como usar el nombre completo de alguien cada vez que se dirige a ellos.

Déjame ponerlo de esta manera. Cuando ves stringcomo un nombre de clase, ¿piensas automáticamente std::stringo mycustom::string? Es como el viejo adagio. Cuando escuchas el sonido de los cascos, piensas en caballos, no en cebras. En otras palabras, using namespace stdcasi siempre no es gran cosa. using namespace mycustomDel mismo modo, generalmente no es un gran problema, a menos que contenga un conflicto std, en cuyo caso su espacio de nombres personalizado es el que desea que siempre requiera el prefijo.

Karl Bielefeldt
fuente
Lo que sucede si mycustomcontiene una stringclase. En la cima tu using namespace mycustom;. A través del resto del código que ahora usa string. Todos los que leen el código piensan que std::stringsolo usted (y algunas personas muy observadoras) están pensando mycustom::string. Aquí has ​​puesto las cebras en el potrero. Ver también stackoverflow.com/q/1452721/14065
Martin York
1
¿No leíste mi última oración? Dije específicamente que si los mycustomconflictos stdcontigo siempre deben requerir el mycustom::prefijo.
Karl Bielefeldt
Yo hice. El problema es que la mayoría de los espacios de nombres no son trivialmente grandes. Saber todo en ellos es aún más difícil (y las futuras versiones del espacio de nombres pueden expandirse). Por lo tanto, incluir un espacio de nombres completo es una receta para el desastre (el uso de elementos específicos (dentro de un pequeño alcance específico es más fácil de controlar)). Si tu código contiene doStuff(int). Y una versión más nueva de mycustomagrega doStuff(double)todo el significado de cualquier llamada a los doStuff(5.5);cambios (potencialmente sin que te des cuenta).
Martin York
3

Al trabajar en Python, uso de x import y (como z) constantemente, para tener nombres claros y concisos para hacer referencia a las importaciones.

Las importaciones son invaluables en una base de código con una jerarquía de espacio de nombres profunda. Esto es especialmente cierto cuando el estándar de estilo para la base de código es PEP 8 , que limita la longitud de la línea a menos de 80 caracteres.

Por ejemplo, considere:

import foo

foo.bar.baz.baf.perform_task(foo.bar.baz.quux.SOME_CONSTANT, foo.bar.alice.bob.preferred_hash_function, '42', foo.bar.magic_numbers.MY_SALT)

Lo que en cambio podría escribirse:

from foo.bar import baf
from foo.bar.alice import bob
from foo.bar.baz.quux import SOME_CONSTANT
from foo.bar.magic_numbers import MY_SALT

baf.perform_task(SOME_CONSTANT, bob.preferred_hash_function, '42', MY_SALT)

Dado que los identificadores de Python distinguen entre mayúsculas y minúsculas y tienen una longitud ilimitada , no nos quedaremos sin nombres, independientemente de cuántos importamos.

Si queremos usar el mismo nombre en nuestro módulo como uno de los módulos que deseamos importar, podemos usar un alias para la importación:

from foo.bar.alice import bob as carol

def bob(x, y):
    print "running bob function"
    return carol(x, y, 42)
pcurry
fuente
0

Depende del programador cuándo usarlo. En mi humilde opinión, es mejor no usarlos en absoluto, especialmente en los archivos de encabezado. Pero hay varios casos cuando lo uso

  • Cuando quiero presentar algo a otro espacio de nombres, por ejemplo

    namespace cg
    {
      namespace details
      {
        //lots of stuff
        void some_cool_foo()
        {
          //uses a lot stuff from details, here because I don't want prefix everything with details::
        }
      }
      using details::some_cool_foo;
    }
    
  • Para habilitar ADL para algunos algoritmos de otro espacio de nombres

    namespace n1
    {
    //some general foo
    }
    namespace n2
    {
      using n1::foo;
    //some struct
    }
    namespace n3
    {
      using n1::foo;
    //some struct
    }
    

Si no quiero escribir nombres largos de espacios de nombres en .cpp, siempre puedo hacer un alias

namespace bl = boost::lambda;
namespace fs = boost::filesystem;
kassak
fuente
lo siento, no pude resaltar mi fuente = /
kassak