Los conflictos de nombres ocurren todo el tiempo en la vida real. Por ejemplo, todas las escuelas a las que asistí tenían al menos dos estudiantes en mi clase que compartían el mismo nombre. Si alguien entrara a la clase y preguntara por el estudiante X, le preguntamos con entusiasmo: "¿De cuál de ellos está hablando? Hay dos estudiantes llamados X". Después de eso, la persona indagante nos daría un apellido, y le presentaríamos la X correcta..
Toda esta confusión y el proceso de determinar la persona exacta de la que estamos hablando al buscar otra información, además del nombre, podrían evitarse si todos tuviéramos un nombre único. Esto no es un problema en una clase de 30 estudiantes. Sin embargo, será cada vez más difícil encontrar un único, significativo y Fácil de recordar nombre para cada niño en una escuela, pueblo, ciudad, país o el mundo entero. Otro problema al proporcionar a cada niño un nombre único es que el proceso de determinar si otra persona también ha nombrado a su hijo Macey, Maci o Macie podría ser muy agotador.
Un conflicto muy similar también puede surgir en la programación. Cuando está escribiendo un programa de solo 30 líneas sin dependencias externas, es muy fácil dar nombres únicos y significativos a todas sus variables. El problema surge cuando hay miles de líneas en un programa y también ha cargado algunos módulos externos. En este tutorial, aprenderá sobre los espacios de nombres, su importancia y la resolución de alcance en Python.
Un espacio de nombres es básicamente un sistema para garantizar que todos los nombres de un programa sean únicos y puedan usarse sin ningún conflicto. Es posible que ya sepa que todo en cadenas, listas, funciones, etc. similares a Python es un objeto. Otro hecho interesante es que Python implementa espacios de nombres como diccionarios. Existe una asignación de nombre a objeto, con los nombres como claves y los objetos como valores. Varios espacios de nombres pueden usar el mismo nombre y asignarlo a un objeto diferente. Aquí hay algunos ejemplos de espacios de nombres:
En la sección Módulos matemáticos en Python sobre Envato Tuts +, escribí sobre funciones matemáticas útiles disponibles en diferentes módulos. Por ejemplo, los módulos math y cmath tienen muchas funciones que son comunes a ambos, como log10 ()
, acos ()
, cos ()
, exp ()
, etc. Si está utilizando ambos de estos módulos en el mismo programa, la única forma de usar estas funciones de manera inequívoca es prefijarlos con el nombre del módulo, como math.log10 ()
y cmath.log10 ()
.
Los espacios de nombres nos ayudan a identificar de forma única todos los nombres dentro de un programa. Sin embargo, esto no implica que podamos usar un nombre de variable en cualquier lugar que queramos. Un nombre también tiene un alcance que define las partes del programa donde podría usar ese nombre sin usar ningún prefijo. Al igual que los espacios de nombres, también hay múltiples ámbitos en un programa. Aquí hay una lista de algunos ámbitos que pueden existir durante la ejecución de un programa..
En las siguientes secciones de este tutorial, usaremos ampliamente la función direc. () De Python para devolver una lista de nombres en el ámbito local actual. Esto le ayudará a comprender el concepto de espacios de nombres y el alcance con mayor claridad..
Como mencioné en la sección anterior, la búsqueda de un nombre dado comienza desde la función más interna y luego se mueve cada vez más alto hasta que el programa puede asignar ese nombre a un objeto. Cuando no se encuentra dicho nombre en ninguno de los espacios de nombres, el programa genera un NameError excepción.
Antes de comenzar, intente escribir dir ()
en IDLE o en cualquier otro IDE de Python.
dir () # ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
Todos estos nombres listados por dir ()
están disponibles en todos los programas de Python. En aras de la brevedad, empezaré a referirme a ellos como '__builtins __' ... '__spec__'
en el resto de los ejemplos.
Veamos la salida de la dir ()
función después de definir una variable y una función.
a_num = 10 dir () # ['__builtins __'… '__spec__', 'a_num'] def some_func (): b_num = 11 print (dir ()) some_func () # ['b_num'] dir () # ['__builtins__ '...' __spec__ ',' a_num ',' some_func ']
los dir ()
La función solo genera la lista de nombres dentro del alcance actual. Es por eso que dentro del ámbito de some_func ()
, solo hay un nombre llamado b_num
. Vocación dir ()
después de definir some_func ()
Lo agrega a la lista de nombres disponibles en el espacio de nombres global..
Ahora, veamos la lista de nombres dentro de algunas funciones anidadas. El código en este bloque continúa desde el bloque anterior..
def outer_func (): c_num = 12 def inner_func (): d_num = 13 print (dir (), '- names in inner_func') e_num = 14 inner_func () print (dir (), '- names in outer_func') outer_func ( ) # ['d_num'] - nombres en inner_func # ['c_num', 'e_num', 'inner_func'] - nombres en outer_func
El código anterior define dos variables y una función dentro del alcance de exterior_func ()
. Dentro inner_func ()
, la dir ()
La función solo imprime el nombre d_num
. Esto parece justo como d_num
Es la única variable definida allí.
A menos que se especifique explícitamente utilizando global
, la reasignación de un nombre global dentro de un espacio de nombres local crea una nueva variable local con el mismo nombre. Esto es evidente a partir del siguiente código..
a_num = 10 b_num = 11 def outer_func (): global a_num a_num = 15 b_num = 16 def inner_func (): global a_num a_num = 20 b_num = 21 print ('a_num inside inner_func:', a_num) print ('b_num inside inner_func: ', b_num) inner_func () imprimir (' a_num inside outer_func: ', a_num) imprimir (' b_num inside outer_func: ', b_num) outer_func () imprimir (' a_num fuera de todas las funciones: ', a_num) imprimir (' b_num fuera de todo funciones: ', b_num) # a_num inside inner_func: 20 # b_num inside inner_func: 21 # a_num inside outer_func: 20 # b_num inside outer_func: 16 # a_num fuera de todas las funciones: 20 # b_num fuera de todas las funciones: 11
Dentro de ambos exterior_func ()
y inner_func ()
, a_num
ha sido declarado como una variable global. Solo estamos configurando un valor diferente para la misma variable global. Esta es la razón por la que el valor de a_num
en todas las ubicaciones es 20. Por otro lado, cada función crea su propia b_num
variable con un alcance local, y la impresión()
La función imprime el valor de esta variable de ámbito local..
Es muy común importar módulos externos en sus proyectos para acelerar el desarrollo. Hay tres formas diferentes de importar módulos. En esta sección, aprenderá sobre todos estos métodos, discutiendo en detalle sus ventajas y desventajas..
desde el módulo de importación *
: Este método de importar un módulo importa todos los nombres del módulo dado directamente en su espacio de nombres actual. Podría sentirse tentado a usar este método porque le permite usar una función directamente sin agregar el nombre del módulo como prefijo. Sin embargo, es muy propenso a errores, y también pierde la capacidad de indicar qué módulo realmente importó esa función. Aquí hay un ejemplo del uso de este método:dir () # ['__builtins __' ... '__spec__'] from math import * dir () # ['__builtins __' ... '__spec__', 'acos', 'acosh', 'asin', 'asinh', # 'atan' , 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', # 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', # 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', # 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', # 'modf', 'nan', 'pi', 'pow', ' radians ',' sin ',' sinh ',' sqrt ',' tan ', #' tanh ',' trunc '] log10 (125) # 2.0969100130080562 de cmath import * dir () # [' __builtins __ '...' __spec__ ' , 'acos', 'acosh', 'asin', 'asinh', 'atan', # 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', # 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', # 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', # 'ldexp', 'lgamma', 'log', 'log10', 'log1p', ' log2 ',' modf ',' nan ',' phase ', #' pi ',' polar ',' pow ',' radians ',' re ct ',' sin ',' sinh ',' sqrt ',' tan ',' tanh ', #' trunc '] log10 (125) # (2.0969100130080562 + 0j)
Si está familiarizado con el mates y cmath módulos, ya sabe que hay algunos nombres comunes que están definidos en ambos módulos pero que se aplican a números reales y complejos respectivamente.
Desde que hemos importado el cmath módulo después de la mates módulo, sobrescribe las definiciones de funciones de estas funciones comunes de la mates módulo. Por eso la primera log10 (125)
Devuelve un número real y el segundo. log10 (125)
devuelve un número complejo. No hay manera de que uses la log10 ()
Funcionar desde el módulo matemático ahora. Incluso si has intentado escribir math.log10 (125)
, obtendrá una excepción NameError porque mates
no existe realmente en el espacio de nombres.
La conclusión es que no debe utilizar esta forma de importar funciones de diferentes módulos solo para guardar unas pocas pulsaciones de teclas..
desde el módulo importar nombre A, nombreB
: Si sabe que solo va a utilizar uno o dos nombres de un módulo, puede importarlos directamente usando este método. De esta manera, puede escribir el código de manera más concisa y al mismo tiempo mantener la contaminación del espacio de nombres al mínimo. Sin embargo, tenga en cuenta que todavía no puede usar ningún otro nombre del módulo usando módulo.nombreZ
. Cualquier función que tenga el mismo nombre en su programa también sobrescribirá la definición de esa función importada desde el módulo. Esto hará que la función importada quede inutilizable. Aquí hay un ejemplo del uso de este método:dir () # ['__builtins __' ... '__spec__'] desde math import log2, log10 dir () # ['__builtins __'… '__spec__', 'log10', 'log2'] log10 (125) # 2.0969100130080562
módulo de importación
: Esta es la forma más segura y recomendada de importar un módulo. El único inconveniente es que tendrá que prefijar el nombre del módulo a todos los nombres que va a utilizar en el programa. Sin embargo, podrá evitar la contaminación del espacio de nombres y también definir funciones cuyos nombres coincidan con el nombre de las funciones del módulo..dir () # ['__builtins __' ... '__spec__'] import math dir () # ['__builtins __'… '__spec__', 'math'] math.log10 (125) # 2.0969100130080562
Espero que este tutorial te haya ayudado a entender los espacios de nombres y su importancia. Ahora debería poder determinar el alcance de los diferentes nombres en un programa y evitar los peligros potenciales.
Además, no dude en ver lo que tenemos disponible para la venta y para estudiar en el mercado, y no dude en hacer cualquier pregunta y proporcionar sus valiosos comentarios utilizando la siguiente información..
La sección final del artículo trata sobre las diferentes formas de importar módulos en Python y las ventajas y desventajas de cada uno de ellos. Si tiene alguna pregunta relacionada con este tema, hágamelo saber en los comentarios..
Aprende Python con nuestra completa guía de tutoriales de Python, ya sea que estés empezando o seas un programador experimentado que busca aprender nuevas habilidades..