proyectos ejemplos python coding-style pycharm

python - ejemplos - django



¿Qué tan malo es el sombreado de los nombres definidos en los ámbitos externos? (7)

Acabo de cambiar a Pycharm y estoy muy contento con todas las advertencias y sugerencias que me proporciona para mejorar mi código. Excepto por este que no entiendo:

This inspection detects shadowing names defined in outer scopes.

Sé que es una mala práctica acceder a la variable desde el alcance externo, pero ¿cuál es el problema con el sombreado del alcance 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)


Depende de la duración de la función. Mientras más larga sea la función, más posibilidades habrá de que alguien que la modifique en el futuro escriba data pensando que significa lo global. De hecho, significa el local, pero debido a que la función es tan larga, no es obvio para ellos que exista un local con ese nombre.

Para su función de ejemplo, creo que seguir a lo global no está nada mal.


Hacer esto:

data = [4, 5, 6] def print_data(): global data print(data) print_data()


No es gran cosa en su fragmento de arriba, pero imagine una función con algunos argumentos más y bastantes líneas más de código. Luego decides renombrar tu argumento de data como yadda pero te pierdes uno de los lugares donde se usa en el cuerpo de la función ... Ahora los data refieren a lo global, y comienzas a tener un comportamiento extraño, donde tendrías un NameError mucho más obvio si no tenías una data nombre global.

También recuerde 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 la función foo en la parte superior de su módulo y la use en algún lugar de su cuerpo de función. Luego agregas un nuevo argumento a tu función y lo llamaste - mala suerte - foo .

Finalmente, las funciones y los tipos incorporados también viven en el mismo espacio de nombres y se pueden sombrear de la misma manera.

Nada de esto es un gran problema si tiene funciones cortas, buenos nombres y una buena cobertura de prueba de unidad, pero bueno, a veces tiene que mantener un código que no sea perfecto y se le advierte sobre posibles problemas que podrían ayudar.


Parece que es un patrón de código 100% pytest

ver:

https://docs.pytest.org/en/latest/fixture.html#conftest-py-sharing-fixture-functions

Tuve el mismo problema, esta es la razón por la que encontré esta publicación;)

# ./tests/test_twitter1.py import os import pytest from mylib import db # ... @pytest.fixture def twitter(): twitter_ = db.Twitter() twitter_._debug = True return twitter_ @pytest.mark.parametrize("query,expected", [ ("BANCO PROVINCIAL", 8), ("name", 6), ("castlabs", 42), ]) def test_search(twitter: db.Twitter, query: str, expected: int): for query in queries: res = twitter.search(query) print(res) assert res

Y advertirá con This inspection detects shadowing names defined in outer scopes.

Para solucionar eso, simplemente mueva su accesorio de twitter a ./tests/conftest.py

# ./tests/conftest.py import pytest from syntropy import db @pytest.fixture def twitter(): twitter_ = db.Twitter() twitter_._debug = True return twitter_

Y elimine el accesorio twitter como en ./tests/test_twitter2.py

# ./tests/test_twitter2.py import os import pytest from mylib import db # ... @pytest.mark.parametrize("query,expected", [ ("BANCO PROVINCIAL", 8), ("name", 6), ("castlabs", 42), ]) def test_search(twitter: db.Twitter, query: str, expected: int): for query in queries: res = twitter.search(query) print(res) assert res

Esto hará feliz QA, Pycharm y todos


Una buena solución en algunos casos puede ser mover el código vars + a otra función:

def print_data(data): print data def main(): data = [4, 5, 6] print_data(data) main()


La respuesta más votada y aceptada actualmente y la mayoría de las respuestas aquí se pierden.

No importa cuánto tiempo su función sea, o cómo usted nombra su variable descriptivamente (para poder minimizar la posibilidad de colisión potencial del nombre).

El hecho de que la variable local de su función o su parámetro coincidan en compartir un nombre en el alcance global es completamente irrelevante. Y, de hecho, no importa cuán cuidadosamente elijas tu nombre de variable local, tu función nunca podrá prever "si mi nombre yadda también se usará como una 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 la entrada desde y desde sus parámetros en la firma, de esa manera no necesita preocuparse de qué es (o será) en alcance global, y entonces el sombreado no es un problema en absoluto.

En otras palabras, el problema de sombreado solo importa cuando su función necesita usar la variable local del mismo nombre Y la variable global. Pero deberías evitar ese diseño en primer lugar. El código del OP no tiene realmente ese problema de diseño. Es solo que PyCharm no es lo suficientemente inteligente y da una advertencia por las dudas. Entonces, solo para que PyCharm sea feliz y también para que nuestro código esté limpio, consulte esta solución que cita la respuesta de silyevsk para eliminar completamente la variable global.

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, corrigiendo / eliminando su problema global, sin ajustar su función local actual.


data = [4, 5, 6] #your global variable def print_data(data): # <-- Pass in a parameter called "data" print data # <-- Note: You can access global variable inside your function, BUT for now, which is which? the parameter or the global variable? Confused, huh? print_data(data)