Pycharmに切り替えたばかりで、コードを改善するためのすべての警告とヒントに非常に満足しています。私が理解できないこのものを除いて:
This inspection detects shadowing names defined in outer scopes.
外部スコープから変数にアクセスするのは悪い習慣ですが、外部スコープをシャドウイングすることの問題は何ですか?
Pycharmから警告メッセージが表示される例を次に示します。
data = [4, 5, 6]
def print_data(data): # <-- Warning: "Shadows 'data' from outer scope
print data
print_data(data)
上記のスニペットでは大したことではありませんが、さらにいくつかの引数とかなり多くのコード行を持つ関数を想像してください。次に、data
引数の名前をyadda
に変更しますが、関数の本体で使用されている場所の1つが欠落しています... data
はグローバルを参照し、奇妙になり始めます振る舞い-グローバル名NameError
を持っていなかった場合、はるかにわかりやすいdata
があります。
また、Pythonではすべてがオブジェクト(モジュール、クラス、および関数を含む)であるため、関数、モジュール、またはクラスには明確な名前空間がないことを忘れないでください。別のシナリオは、モジュールの最上部で関数foo
をインポートし、関数本体のどこかで使用することです。次に、関数に新しい引数を追加し、名前を付けます-不運-foo
。
最後に、組み込みの関数と型も同じ名前空間に存在し、同じ方法でシャドウイングできます。
短い関数、適切な名前付け、まともな単体テストのカバレッジがある場合、これは問題になりませんが、完璧でないコードを維持する必要があり、そのような可能性のある問題について警告されると役立つ場合があります。
現在最も多く投票され受け入れられている回答 で、ほとんどの回答はポイントを逃しています。
関数の長さや、変数に記述的に名前を付ける方法は問題ではありません(名前の衝突の可能性を最小限に抑えるためです)。
関数のローカル変数またはそのパラメーターがグローバルスコープ内で名前を共有するという事実は、まったく無関係です。実際、ローカル変数名をどれだけ慎重に選択しても、関数は「将来、私のクールな名前yadda
もグローバル変数として使用されるかどうか」を予測できません。ソリューション?心配しないでください! 正しい考え方は、署名のパラメーターからの入力のみを使用するように関数を設計することです、そのように何を気にする必要はありません(または、グローバルスコープ内にあり、シャドウイングはまったく問題になりません。
言い換えれば、シャドーイングの問題は、関数が同じ名前のローカル変数とグローバル変数を使用する必要がある場合にのみ問題になります。ただし、そもそもこのような設計は避けてください。 OPのコードには、実際にはそのような設計上の問題はありません。 PyCharmが十分に賢くなく、念のため警告を発するだけです。したがって、PyCharmを幸せにし、コードをきれいにするために、 silyevskの答え から引用したこのソリューションを参照して、グローバル変数を完全に削除してください。
def print_data(data):
print data
def main():
data = [4, 5, 6]
print_data(data)
main()
これは、現在のローカル機能を調整するのではなく、グローバルなものを修正/削除することにより、この問題を「解決」する適切な方法です。
場合によっては、vars +コードを別の関数に移動することをお勧めします。
def print_data(data):
print data
def main():
data = [4, 5, 6]
print_data(data)
main()
これを行う:
data = [4, 5, 6]
def print_data():
global data
print(data)
print_data()
関数の長さによって異なります。関数が長いほど、将来誰かがそれを変更する可能性が高くなり、それがグローバルを意味すると考えるdata
を書くようになります。実際にはローカルを意味しますが、関数が非常に長いため、その名前のローカルが存在することは彼らには明らかではありません。
関数の例では、グローバルをシャドウイングすることはまったく悪くないと思います。
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)
100%pytestのコードパターンのように見えます
見る:
https://docs.pytest.org/en/latest/fixture.html#conftest-py-sharing-fixture-functions
私は同じ問題を抱えていました、これが私がこの投稿を見つけた理由です;)
# ./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
そして、This inspection detects shadowing names defined in outer scopes.
で警告します
これを修正するには、Twitter
フィクスチャを./tests/conftest.py
に移動するだけです
# ./tests/conftest.py
import pytest
from syntropy import db
@pytest.fixture
def Twitter():
Twitter_ = db.Twitter()
Twitter_._debug = True
return Twitter_
そして./tests/test_Twitter2.py
のようなTwitter
フィクスチャを削除します
# ./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
これはQA、Pycharm、そしてみんなを幸せにするでしょう