외부 스코프에서 정의된 섀도우 이름의 문제는 무엇입니까?
방금 PyCharm으로 전환했는데 코드 개선을 위한 모든 경고와 힌트에 매우 만족하고 있습니다.내가 이해할 수 없는 것을 제외하고:
이 검사는 외부 스코프에 정의된 섀도우 이름을 검출합니다.
외부 스코프에서 변수에 액세스하는 것은 좋지 않은 관행이라는 것은 알고 있습니다만, 외부 스코프에 음영을 주는 것은 어떤 문제입니까?
다음 예시는 PyCharm이 경고 메시지를 표시하는 예입니다.
data = [4, 5, 6]
def print_data(data): # <-- Warning: "Shadows 'data' from outer scope
print data
print_data(data)
위의 스니펫에는 큰 문제가 없지만, 몇 개의 인수와 몇 줄의 코드가 있는 함수를 상상해 보세요. 이름을 요.data
yadda
함수 본문에서 사용되는 위치 중 하나를 놓칩니다., 이제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()
이것은 현재의 로컬 기능을 조정하는 것이 아니라 글로벌한 것을 수정/제거함으로써 이 문제를 해결하는 적절한 방법입니다.
경우에 따라서는 변수와 코드를 다른 함수로 이동하는 것이 좋습니다.
def print_data(data):
print data
def main():
data = [4, 5, 6]
print_data(data)
main()
PyCharm 오른쪽 상단 모서리에 녹색 체크 표시가 있는 것을 좋아합니다.중요한 경고에 집중할 수 있도록 이 경고를 지우려면 변수 이름에 밑줄을 추가합니다.
data = [4, 5, 6]
def print_data(data_):
print(data_)
print_data(data)
기능의 길이에 따라 달라집니다.하는 사람이 쓸 .data
한다고 생각합니다글로벌'을 의미한다고 생각하면서요.사실 로컬을 의미하지만 함수가 너무 길기 때문에 그런 이름의 로컬이 존재하는지는 분명하지 않습니다.
당신의 예시로, 저는 지구 쉐도우잉이 전혀 나쁘지 않다고 생각합니다.
다음을 수행합니다.
data = [4, 5, 6]
def print_data():
global data
print(data)
print_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 코드 패턴인 것 같습니다.
참조:
저도 같은 문제를 안고 있었기 때문에, 이 투고를 발견하게 되었습니다.
# ./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_
,를 합니다.twitter
고정 장치, 예를 들어./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
이것은 QA, PyCharm, 그리고 모두에게 행복할 것입니다.
Chistopher가 댓글에서 말한 것처럼 경고를 무시하려면 그 위에 댓글을 달 수 있습니다.
# noinspection PyShadowingNames
이 규칙은 별로 도움이 되지 않는 것 같아요.저는 단지 그것을 무효로 했을 뿐입니다.Settings
->Editor
->Inspections
다음으로 이 규칙을 체크합니다.
Shadowing names from outer scope
언급URL : https://stackoverflow.com/questions/20125172/what-is-the-problem-with-shadowing-names-defined-in-outer-scopes
'programing' 카테고리의 다른 글
표의 모든 열을 나열하려면 어떻게 해야 합니까? (0) | 2022.10.02 |
---|---|
외부 키 제약 조건에 사용된 열을 변경할 수 없습니다. (0) | 2022.10.02 |
fs: 부모 폴더를 찾으려면 어떻게 해야 하나요? (0) | 2022.10.02 |
JUnit4 fail()은 여기에 있는데 pass()는 어디에 있나요? (0) | 2022.10.02 |
문자열에서 숫자가 아닌 문자( 마침표 및 쉼표 제외)를 제거합니다(숫자, 쉼표 및 마침표를 제외한 모든 문자 제거). (0) | 2022.10.02 |