¿Cuál es el problema con el sombreado de nombres definidos en ámbitos externos?
Acabo de cambiarme a PyCharm y estoy muy contento con todas las advertencias y sugerencias que me brinda para mejorar mi código. Excepto este que no entiendo:
Esta inspección detecta nombres ocultos definidos en ámbitos externos.
Sé que es una mala práctica acceder a variables desde el ámbito externo, pero ¿cuál es el problema de seguir el ámbito externo?
Aquí hay un ejemplo, donde PyCharm me da el mensaje de advertencia:
data = [4, 5, 6]
def print_data(data): # <-- Warning: "Shadows 'data' from outer scope
print data
print_data(data)
No hay gran cosa en el fragmento anterior, pero imagina una función con algunos argumentos más y bastantes líneas de código más. Luego decide cambiar el nombre de su data
argumento como yadda
, pero omite uno de los lugares donde se usa en el cuerpo de la función... Ahora data
se refiere a lo global y comienza a tener un comportamiento extraño, donde tendría un resultado mucho más obvio NameError
si no lo hiciera. No tiene un nombre global data
.
Recuerde también que en Python todo es un objeto (incluidos módulos, clases y funciones), por lo que no hay espacios de nombres distintos para funciones, módulos o clases. Otro escenario es que importe una función foo
en la parte superior de su módulo y la use en algún lugar del cuerpo de su función. Luego agrega un nuevo argumento a su función y lo nombra - mala suerte - foo
.
Finalmente, las funciones y tipos integrados también se encuentran en el mismo espacio de nombres y se pueden sombrear de la misma manera.
Nada de esto es un gran problema si tienes funciones cortas, buenos nombres y una cobertura de prueba unitaria decente, pero bueno, a veces tienes que mantener un código que no es perfecto y recibir advertencias sobre estos posibles problemas puede ayudar.
La respuesta más votada y aceptada actualmente y la mayoría de las respuestas aquí no entienden el punto.
No importa qué tan larga sea su función o cómo nombre su variable de manera descriptiva (con suerte, para minimizar la posibilidad de una posible colisión de nombres).
El hecho de que la variable local de su función o su parámetro comparta un nombre en el ámbito global es completamente irrelevante. Y, de hecho, no importa cuán cuidadosamente elija el nombre de su variable local, su función nunca podrá prever "¿si mi nombre genial yadda
también se usará como variable global en el futuro?". ¿La solución? ¡Simplemente no te preocupes por eso! La mentalidad correcta es diseñar su función para consumir entradas desde y solo desde sus parámetros en la firma . De esa manera, no es necesario que le importe lo que está (o estará) en el alcance global, y entonces el seguimiento dejará de ser un problema en absoluto.
En otras palabras, el problema del sombreado solo importa cuando su función necesita usar la variable local y la variable global con el mismo nombre. Pero, en primer lugar, deberías evitar ese tipo de diseño. El código del OP realmente no tiene ese problema de diseño. Es sólo que PyCharm no es lo suficientemente inteligente y da una advertencia por si acaso. Entonces, solo para hacer feliz a PyCharm y también limpiar nuestro código, vea esta solución que cita la respuesta de silyevsk para eliminar la variable global por completo.
def print_data(data):
print data
def main():
data = [4, 5, 6]
print_data(data)
main()
Esta es la forma correcta de "resolver" este problema, arreglando/eliminando su elemento global, sin ajustar su función local actual.
Una buena solución en algunos casos puede ser mover las variables y el código a otra función:
def print_data(data):
print data
def main():
data = [4, 5, 6]
print_data(data)
main()
Me gusta ver una marca verde en la esquina superior derecha de PyCharm. Agrego los nombres de las variables con un guión bajo solo para borrar esta advertencia y poder concentrarme en las advertencias importantes.
data = [4, 5, 6]
def print_data(data_):
print(data_)
print_data(data)
Depende de cuánto tiempo dure la función. Cuanto más larga sea la función, mayor será la posibilidad de que alguien que la modifique en el futuro escriba data
pensando que significa global. De hecho, significa local, pero debido a que la función es tan larga, no les resulta obvio que exista un local con ese nombre.
Para su función de ejemplo, creo que seguir lo global no está nada mal.