python的作用域问题
高洛峰
高洛峰 2017-04-18 09:29:09
0
4
738
x = 3
y = [3]

def test1():
    x += 1
    print x

def test2():
    y[0] = 4
    y.append(5)
    print y

test2()
test1()

这段代码执行结果: test2()成功打印[4, 5], test1()却报错: UnboundLocalError: local variable 'x' referenced before assignment

想不明白,为什么会这样,全局变量在函数里可以直接打印,但是如果要改变它的值,会报错,但是test2()为什么不报错?如果把y换成dict类型,就能在函数里不需要用global声明,可以直接改变y的值,但如果是str或number,就会报错,为什么?

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

모든 응답(4)
洪涛

사실 이 질문은 변수가 참조하는 객체가 가변인지 불변인지는 제쳐두어도 됩니다. 우리가 주목해야 할 것은 변수의 위치 , 시점 및 범위입니다. 정의.

다음 코드를 고려하세요.

으아악

이 코드는 오류를 발생시킵니다:

으아악

atest 함수의 param 변수이므로 지역 변수에 속하며, 그 범위는 test 함수를 참조하도록 1을 전달하므로 큰 문제는 없습니다. print(a)과 함께.
그런데 b은 처음부터 끝까지 정의되어 있지 않아서 LEGB 원칙에 따라 검색해도 찾을 수 없어서 NameError을 띄웁니다.

이 문제를 해결하기 위해 전역 변수를 정의할 수 있습니다.

으아악

좋아 이번에는 문제가 없을 것 같습니다. Python이 전역 범위에서 b을 찾았기 때문입니다. Python이 전역 b을 사용하는 이유는 b을 로컬에 정의하지 않았기 때문입니다.

그런 다음 함수에 변수를 할당하기 시작합니다.

으아악

결과:

으아악

함수에 있는 두 print는 1과 20으로 출력되는데, 함수를 떠난 후 출력된 b의 값은 왜 100이 되었나요?
함수 A에 이렇게 썼기 때문입니다 할당 정의 b = 20이기도 하므로 test에 표시된 b은 전역이 아닌 모두 로컬이므로 b에 대한 변경 사항은 전역 . b

이 사실은 다음과 같습니다.

로컬 변수가 정의되지 않은 경우 Python은 자동으로 전역 변수를 사용하고, 그렇지 않으면 사용하지 않습니다.

그렇다면 함수 내에서 전역 변수를 어떻게 작동할 수 있습니까?

키워드의 도움이 필요합니다: global 으아악 으아악

을 설명하는 global 키워드를 사용하면 Python은 btest을 전역 b에 액세스하기 위한 변수로 처리하고 b는 다음과 같이만 처리됩니다. 할당 작업은 새로운 지역 변수. b = 20

좀 더 이해하기 어려운 예를 살펴보겠습니다.

으아악

결과:

으아악

이 여기에

나타납니다. 이유는 매우 간단합니다. UnboundLocalError에는 b 함수에 할당 및 정의 작업이 있으므로 b = 20 내부의 test는 로컬(전역)입니다. 여기서는 b이 전역임을 나타내기 위해 사용되지 않으므로 b을 사용하면 Python은 전역 print(b) 대신 로컬 b을 가져오려고 시도하지만 여기서 비극은 첫 번째 단계에서 로컬 b이 할당되지 않아서 할당되기 전에 b을 참조했다고 하는데 이는 당연히 불가능하다. local variable 'b' referenced before assignment

당신이 제시한 예를 되돌아보세요:

으아악

여기서 test1의 정의는 x에 나옵니다(전역은 없고 x은 등호 왼쪽에 나타납니다). 당연히 x을 언급할 때, 로컬을 사용하지만 이유:

으아악

그래서 등호 오른쪽에 있는 x에서 참조하는 값을 얻으려면 아직 값이 할당되지 않은 것을 알 수 있습니다. 그러면 위의 예와 같습니다.

으아악

귀하의 test2에는 문제가 없습니다.

으아악

test2의 등호 왼쪽에 y가 나오지 않기 때문에 Python은 자동으로 전역 y을 사용한 것으로 가정하므로 당연히 문제가 없습니다.

결론

  1. 함수에 지역 변수가 정의되어 있는지 확인하려면 변수 이름이 등호 왼쪽에 나타나는지,

    global

    에 변수 이름이 지정되어 있지 않은지 확인하세요.
  2. 로컬 변수가 정의된 경우 Python은 전역 변수를 찾지 않습니다. 그렇지 않으면 Python은 자동으로 전역 변수를 사용합니다

  3. 로컬 변수가 정의되어 있지만 변수가 할당되기 전에 참조를 읽으면 UnboundLocalError가 나타납니다

  4. 이 문제를 해결하려면 전체 도메인을 나타내기 위해

    를 추가해야 한다는 점을 기억하세요. 그렇지 않으면 이 작성 방법이 나타나지 않아야 합니다(내부 작업 또는 나중에 할당)global

  5. 로컬 기능에서도 비슷한 문제가 발생합니다. 해결 방법은

    (Python3)을 추가하는 것이지만 그것은 또 다른 이야기입니다. nonlocal


내가 답변한 질문: Python-QA

洪涛

Python의 변수 범위는 이렇게 규정되어 있습니다. test1에서는 print x x를 수정할 수는 있지만
어떤 사람들은 "로컬 범위의 전역 변수는 읽기 전용이어야 합니다"라고 말하지만, 이는 사실이 아닙니다. 이 조건을 참조하십시오. . .

Python에서 이 부분은 정말 헷갈립니다

Peter_Zhu

간단히 말하면 전역 변수의 바인딩은 로컬 범위에서 변경할 수 없으며 변수의 주소는 CPython에서 변경할 수 없습니다.

참조: 일반적인 실수 4: Python 프로그래머가 저지르는 가장 일반적인 10가지 실수: Python의 변수 이름 구문 분석에 대한 오해

伊谢尔伦

test1 함수에는 Python 인터프리터가 함수의 로컬 범위에 있는 변수로 간주하는 할당 작업 x += 1이 있습니다. 그러나 x 변수는 할당 전에 정의되지 않습니다. xnumber이며 불변 유형에 속합니다. 불변 유형에 새 값을 할당하려면 불변 유형 객체를 다시 만들고 원래 변수를 새로 생성된 객체를 다시 가리켜야 합니다. 새로 생성된 객체는 LEGB에 포함되지 않습니다. 찾을 수 없으므로 오류가 보고됩니다

test2 함수에서 y은 변수 유형인 list입니다. 목록은 변수 유형이고 내부에서 수정될 수 있기 때문입니다. , 오류를 보고하지 않습니다

Python의 모든 할당 작업은 기본적으로 다음 세 단계로 구분됩니다(예: a = 3 사용).

  1. 값을 나타내는 개체 만들기3

  2. 아직 생성되지 않은 경우 변수 a를 생성합니다.

  3. a 변수를 새 개체 3

  4. 에 연결합니다.

test2 함수y 실행 중

변수의 메모리 주소 변경을 관찰해 보겠습니다. 으아악

출력

으아악

y이 실제로 수정된 것을 볼 수 있으므로 변수를 반복적으로 생성할 필요가 없으며 x 불변 유형의 경우 값을 할당하려면 먼저 새 객체를 생성해야 합니다. 이름이 동일하더라도 매번 다른 할당이 수행되면 x의 메모리 주소가 실제로 다르다는 것을 알 수 있으며 이는 str 또는 number이 오류를 보고하는 이유도 설명할 수 있습니다

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!