¿Cuál es el problema con el sombreado de nombres definidos en ámbitos externos?

Resuelto Framester asked hace 11 años • 12 respuestas

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)
Framester avatar Nov 21 '13 22:11 Framester
Aceptado

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 dataargumento como yadda, pero omite uno de los lugares donde se usa en el cuerpo de la función... Ahora datase refiere a lo global y comienza a tener un comportamiento extraño, donde tendría un resultado mucho más obvio NameErrorsi 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 fooen 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.

bruno desthuilliers avatar Nov 21 '2013 15:11 bruno desthuilliers

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 yaddatambié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.

RayLuo avatar Oct 12 '2016 21:10 RayLuo

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()
silyevsk avatar Aug 29 '2016 08:08 silyevsk

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)
Baz avatar Feb 22 '2020 15:02 Baz

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

Steve Jessop avatar Nov 21 '2013 15:11 Steve Jessop