파이썬 변수의 범위 관련 질문
조회수 1045회
a=0
def vartest(a):
a=1
return a
print(vartest(a))
왜 a=0
을 지우면 a가 정의되지 않았다고 하나요? 함수 안의 a와 함수 밖의 a는 다른 변수이기 때문에 a=0
의 유무와 상관없이 함수 내에서 a=1
이라고 정의했으니, print(vartest(a))
를 실행했을 때 a=1 print(a)
을 실행한 것과 같은 결과가 나와야 하는 것 아닌가요?
1 답변
-
a=0 def vartest(a): a=1 return a print(vartest(a)) print(a) 결과: 1 0
질문자의 본 질문인 a 가 없다고 하는 이유는 vartest(a) 를 호출할 때 a라는 변수가 없는 상황이기 때문입니다. 즉 전역으로 설정한 a = 0 을 지우고 vartest(a) 를 호출하면 당연히 a변수가 없는 상황이기 때문에 a가 정의되지 않았다고 하는 겁니다.
그런데 조금 더 나아가 위의 결과는 파이썬 프로그래밍을 할 때 중요한 포인트를 알려줍니다.
질문자는 단순히 왜 에러가 발생하는지를 물었지만 사실 위의 질문에서 더 중요한 질문은 함수 호출뒤 a값이 왜 1이 아닌지 입니다.
파이썬에서는 명시적인 call by reference 가 불가능합니다. 여기서 명시적이라는 의미는 c에서 & 같은 연산자가 없다는 의미입니다.
다만 파이썬에서는 전달되는 파라미터 타입에 따라 call by value 혹은 call by reference 를 선택 적용하게 됩니다.
구체적으로 int, float, tuple 같은 변경불가능한 객체는 call by value 로 전달됩니다. 즉 값을 복사합니다. 값만 복사하므로 원본 객체는 변함이 없습니다. 즉 위의 예에서 1로 변경을 해도 원본 a 객체는 변함없이 0 인 겁니다.
그러나 list, dict 같은 변경가능한 객체들은 call by reference 로 전달이 됩니다. 레퍼런스가 전달되므로 함수에서 인자로 전달후 추가 혹은 삭제등의 변경을 하면 전달했던 원본 객체도 변하게 됩니다.
- 상세한 답변 감사합니다. 다만 입문한지 얼마 되지 않아서 4번째 단락에서부턴 처음 들어보는 단어들이 많네요..ㅎㅎ 더 공부하다 이해가 좀 되었다 싶으면 다시 보겠습니다! limephan 2019.4.11 13:46
- 아직 4번째 단락부턴 이해하지 못했지만 질문에 대해선 해결한 것 같습니다. 두 줄의 print()는 결국 print(vartest(0), print(0)을 한 것과 같은 게 맞는거죠? 전자의 경우 인수(argument) 0을 받아서 코드 블록대로 실행해 1을 출력했고 후자의 경우는 함수 밖의 변수 a에 0을 대입해 0을 출력한 것이었네요. limephan 2019.4.11 20:22
댓글 입력