목록 이해는 이해 범위 이후에도 이름을 다시 바인딩합니다.이게 맞나
이해 관계는 범위 지정과 비정상적인 상호 작용을 보여줍니다.이것이 예상된 행동입니까?
x = "original value"
squares = [x**2 for x in range(5)]
print(x) # Prints 4 in Python 2!
징징거릴 위험을 무릅쓰고, 이것은 잔인한 오류의 근원입니다.제가 새로운 코드를 쓸 때, 저는 가끔 리바인딩으로 인해 매우 이상한 오류를 발견합니다. 문제가 있다는 것을 알고도 말이죠.저는 "항상 밑줄이 있는 목록 이해에서 임시 변수를 서문으로 작성해야 합니다."와 같은 규칙을 만들어야 하지만, 그것조차도 완벽한 것은 아닙니다.무작위 시한 폭탄이 기다리고 있다는 사실은 목록 이해의 모든 좋은 "사용 편의성"을 부정합니다.
목록 이해는 Python 2에서는 루프 제어 변수를 누출하지만 Python 3에서는 누출하지 않습니다.Python의 제작자인 Guido van Rossum이 이에 대한 역사를 설명합니다.
우리는 또한 Python 3에서 목록 이해와 생성기 표현식 간의 동등성을 개선하기 위해 또 다른 변경을 가했습니다.Python 2에서 목록 이해는 루프 제어 변수를 주변 범위로 "누출"합니다.
x = 'before' a = [x for x in 1, 2, 3] print x # this prints '3', not 'before'
이것은 목록 이해의 원래 구현의 인공물이었습니다. 이것은 수년 동안 Python의 "더러운 작은 비밀" 중 하나였습니다.그것은 목록 이해를 눈 깜짝할 사이에 빠르게 하기 위한 의도적인 타협으로 시작되었고, 초보자들에게 흔한 함정은 아니었지만, 확실히 때때로 사람들을 찔렀습니다.제너레이터 식의 경우 이 작업을 수행할 수 없습니다.생성기 식은 생성기를 사용하여 구현되며, 생성기의 실행에는 별도의 실행 프레임이 필요합니다.따라서 생성기 식(특히 짧은 시퀀스에 걸쳐 반복되는 경우)은 목록 이해보다 효율성이 떨어졌습니다.
그러나 Python 3에서는 생성기 식과 동일한 구현 전략을 사용하여 목록 이해의 "더러운 작은 비밀"을 수정하기로 결정했습니다.따라서 Python 3에서 위의 예제(print(x) :-)를 사용하도록 수정한 후에 'before'를 인쇄하여 목록 이해의 'x'가 일시적으로 그림자를 드리우지만 주변 범위의 'x'를 재정의하지 않음을 증명합니다.
예, 목록 이해는 루프와 마찬가지로 Python 2.x에서 변수를 "누설"합니다.
돌이켜보면, 이것은 실수로 인식되었고, 발전기 표현으로 회피되었습니다.편집: Matt B.가 지적했듯이, Python 3에서 설정 및 사전 이해 구문을 백포트할 때도 방지되었습니다.
리스트 이해의 동작은 Python 2에서 그대로 두어야 했지만, Python 3에서는 완전히 수정되었습니다.
이는 다음과 같은 모든 경우에 해당합니다.
list(x for x in a if x>32)
set(x//4 for x in a if x>32) # just another generator exp.
dict((x, x//16) for x in a if x>32) # yet another generator exp.
{x//4 for x in a if x>32} # 2.7+ syntax
{x: x//16 for x in a if x>32} # 2.7+ syntax
그자리의 x
다음과 같은 경우에는 항상 식에 로컬입니다.
[x for x in a if x>32]
set([x//4 for x in a if x>32]) # just another list comp.
dict([(x, x//16) for x in a if x>32]) # yet another list comp.
2 Python 2.x에서 됩니다.x
주변 범위에 대한 변수입니다.
Python 3.8용 업데이트: PEP 572 도입:=
의도적으로 이해와 생성자 식에서 유출되는 할당 연산자!이러한 유출은 기본적으로 두 가지 사용 사례에 의해 유발되었습니다. 다음과 같은 조기 종료 기능에서 "증인"을 캡처하는 것입니다.any()
그리고.all()
:
if any((comment := line).startswith('#') for line in lines):
print("First comment:", comment)
else:
print("There are no comments")
및 변경 가능한 상태 업데이트:
total = 0
partial_sums = [total := total + v for v in values]
정확한 범위 지정은 부록 B를 참조하십시오.변수는 가장 가까운 주변 환경에 할당됩니다.def
또는lambda
함수가 그것을 한.nonlocal
또는global
.
네, 과제는 그곳에서 발생합니다. 마치 나중에 발생하는 것처럼.for
루프. 새 스코프가 생성되지 않습니다.
이것은 확실히 예상되는 동작입니다. 각 사이클에서 값은 지정한 이름에 바인딩됩니다.예를 들어.
>>> x=0
>>> a=[1,54,4,2,32,234,5234,]
>>> [x for x in a if x>32]
[54, 234, 5234]
>>> x
5234
이를 인식하면 쉽게 피할 수 있을 것으로 보입니다. 이해 범위 내 변수에 기존 이름을 사용하지 마십시오.
흥미롭게도 이것은 사전이나 집합 이해에 영향을 주지 않습니다.
>>> [x for x in range(1, 10)]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x
9
>>> {x for x in range(1, 5)}
set([1, 2, 3, 4])
>>> x
9
>>> {x:x for x in range(1, 100)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15, 16: 16, 17: 17, 18: 18, 19: 19, 20: 20, 21: 21, 22: 22, 23: 23, 24: 24, 25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30, 31: 31, 32: 32, 33: 33, 34: 34, 35: 35, 36: 36, 37: 37, 38: 38, 39: 39, 40: 40, 41: 41, 42: 42, 43: 43, 44: 44, 45: 45, 46: 46, 47: 47, 48: 48, 49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57, 58: 58, 59: 59, 60: 60, 61: 61, 62: 62, 63: 63, 64: 64, 65: 65, 66: 66, 67: 67, 68: 68, 69: 69, 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, 75: 75, 76: 76, 77: 77, 78: 78, 79: 79, 80: 80, 81: 81, 82: 82, 83: 83, 84: 84, 85: 85, 86: 86, 87: 87, 88: 88, 89: 89, 90: 90, 91: 91, 92: 92, 93: 93, 94: 94, 95: 95, 96: 96, 97: 97, 98: 98, 99: 99}
>>> x
9
그러나 위에서 언급한 것처럼 3개로 고정되었습니다.
이 동작이 바람직하지 않은 경우 python 2.6에 대한 몇 가지 해결 방법
# python
Python 2.6.6 (r266:84292, Aug 9 2016, 06:11:56)
Type "help", "copyright", "credits" or "license" for more information.
>>> x=0
>>> a=list(x for x in xrange(9))
>>> x
0
>>> a=[x for x in xrange(9)]
>>> x
8
목록 이해 중인 python3에서 변수는 범위가 끝난 후 변경되지 않지만 단순 for-loop을 사용하면 변수가 범위 밖으로 재할당됩니다.
i = 1 print(i) print(i in range(5)]) print(i) i 값은 1만 유지됩니다.
이제 단순히 루프에 사용하면 i의 값이 다시 할당됩니다.
언급URL : https://stackoverflow.com/questions/4198906/list-comprehension-rebinds-names-even-after-scope-of-comprehension-is-this-righ
'source' 카테고리의 다른 글
높이와 너비는 스판에 적용되지 않습니까? (0) | 2023.07.28 |
---|---|
"치명적 오류: 다시 선언할 수 없음" (0) | 2023.07.28 |
중앙 컨텐츠를 대응하는 부트스트랩 탐색 모음에 배치 (0) | 2023.07.28 |
PowerShell에서 절대 경로를 상대 경로로 변환하는 방법은 무엇입니까? (0) | 2023.07.28 |
감지되지 않은 오류:'AppModule' 모듈에서 예기치 않은 모듈 'FormsModule'을(를) 선언했습니다.@Pipe/@Directive/@Component 주석을 추가하십시오. (0) | 2023.07.28 |