Je viens de passer à Pycharm et je suis très heureux de tous les avertissements et astuces que cela me fournit pour améliorer mon code. Sauf celui-ci que je ne comprends pas:
This inspection detects shadowing names defined in outer scopes.
Je sais que l’accès à une variable à partir de la portée externe est une mauvaise pratique, mais quel est le problème d’observation de la portée externe?
Voici un exemple où Pycharm me donne le message d'avertissement:
data = [4, 5, 6]
def print_data(data): # <-- Warning: "Shadows 'data' from outer scope
print data
print_data(data)
Ce n'est pas grave, mais imaginez une fonction avec quelques arguments supplémentaires et quelques lignes de code. Ensuite, vous décidez de renommer votre argument data
en yadda
mais vous ratez l’un des endroits où il est utilisé dans le corps de la fonction ... Maintenant data
fait référence au global, et vous commencez à avoir des choses étranges. comportement - où vous auriez une beaucoup plus évidente NameError
si vous n'aviez pas de nom global data
.
Rappelez-vous également que, dans Python, tout est un objet (y compris les modules, les classes et les fonctions); il n'y a donc pas d'espaces de nommage distincts pour les fonctions, les modules ou les classes. Un autre scénario consiste à importer la fonction foo
en haut de votre module et à l’utiliser quelque part dans le corps de votre fonction. Ensuite, vous ajoutez un nouvel argument à votre fonction et vous le nommez - malchance - foo
.
Enfin, les fonctions et les types intégrés résident également dans le même espace de noms et peuvent être observés de la même manière.
Rien de tout cela n’est un gros problème si vous avez des fonctions courtes, une bonne dénomination et une couverture décente, mais bon, vous devez parfois maintenir un code moins que parfait et être prévenu de ce genre de problèmes pourrait aider.
La réponse la plus votée et la plus acceptée à l'heure actuelle et la plupart des réponses omises ici.
Peu importe la longueur de votre fonction ou la façon dont vous appelez votre variable de manière descriptive (pour minimiser, espérons-le, le risque de collision de nom).
Le fait que la variable locale de votre fonction ou son paramètre partage un nom dans l'étendue globale n'a aucune pertinence. Et en fait, quel que soit le soin avec lequel vous choisissez votre nom de variable locale, votre fonction ne peut jamais prévoir "si mon nom génial yadda
sera également utilisé à l'avenir comme variable globale?". La solution? Ne vous inquiétez pas pour ça! Le bon état d'esprit est de concevoir votre fonction pour qu'elle consomme l'entrée et uniquement à partir de ses paramètres dans la signature , afin que vous n'ayez pas à vous soucier de ce qui est ( ou sera) dans une portée globale, puis l'observation ne devient plus un problème.
En d'autres termes, le problème d'observation est important uniquement lorsque votre fonction doit utiliser le même nom, variable locale ET variable globale. Mais vous devriez éviter une telle conception en premier lieu. Le code de l'OP N'A PAS vraiment de problème de conception. PyCharm n’est pas assez intelligent et donne un avertissement au cas où. Donc, juste pour rendre PyCharm heureux et pour rendre notre code propre, voyez cette solution en citant la réponse de silyevsk pour supprimer complètement la variable globale.
def print_data(data):
print data
def main():
data = [4, 5, 6]
print_data(data)
main()
C’est le bon moyen de "résoudre" ce problème, en corrigeant/supprimant votre problème global, sans ajuster votre fonction locale actuelle.
Une bonne solution dans certains cas peut être de déplacer le vars + code vers une autre fonction:
def print_data(data):
print data
def main():
data = [4, 5, 6]
print_data(data)
main()
Faire ceci:
data = [4, 5, 6]
def print_data():
global data
print(data)
print_data()
Cela dépend de la durée de la fonction. Plus la fonction est longue, plus il est probable que quelqu'un la modifiant à l'avenir écrive data
en pensant qu'il s'agit du global. En fait, cela signifie local, mais comme la fonction est longue, il n’est pas évident qu’il existe un local portant ce nom.
Pour votre fonction d'exemple, je pense que l'observation du global n'est pas mal du tout.
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)
On dirait que c'est 100% code de code pytest
voir:
https://docs.pytest.org/fr/latest/fixture.html#conftest-py-sharing-fixture-functions
J'ai eu le même problème avec, c'est pourquoi j'ai trouvé ce post;)
# ./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
Et il avertira avec This inspection detects shadowing names defined in outer scopes.
Pour résoudre ce problème, déplacez simplement votre appareil Twitter
dans ./tests/conftest.py
# ./tests/conftest.py
import pytest
from syntropy import db
@pytest.fixture
def Twitter():
Twitter_ = db.Twitter()
Twitter_._debug = True
return Twitter_
Et retirez Twitter
appareil comme dans ./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
Cela fera plaisir à QA, à Pycharm et à tout le monde