AD JB Toolbox 01

Python 강좌 / 변수의 범위와 변경 가능한 객체의 동작 이해하기

변수의 범위는 이름을 어디에서 찾을지 정하고, 객체의 변경 가능성은 같은 값을 가리키는 이름 사이에 어떤 변화가 보일지 정합니다. 대입과 객체 변경을 구분하면 함수 호출 뒤 데이터가 뜻밖에 바뀌는 원인을 이해할 수 있습니다.

지역 이름과 외부 이름

함수 안에서 대입하는 이름은 별도 선언이 없다면 지역 변수로 취급됩니다. 함수에서 외부 값을 읽는 것과 외부 이름에 새 값을 대입하는 것은 다릅니다. 전역 변수에 의존하기보다 필요한 값을 인수로 받고 결과를 반환하면 테스트하기 쉽습니다.

관련 동작과 지원 조건은 변수의 범위와 변경 가능한 객체의 동작 이해하기 관련 공식 문서에서 확인할 수 있습니다.

global은 모듈 수준 이름, nonlocal은 바깥 함수의 이름 연결을 바꿀 때 사용합니다. 모든 상태 문제를 이 선언으로 해결하려 하지 말고 데이터 전달 구조를 먼저 검토합니다.

전체 예제와 실행 결과

별도의 실습 폴더에서 아래 파일을 UTF-8로 저장합니다. 가상환경을 선택한 터미널에서 python scope.py 명령으로 실행합니다. macOS·Ubuntu에서 가상환경을 사용하지 않는 경우 명령 이름을 python3으로 바꿉니다.

scope.py 파일의 전체 내용입니다.

def add_fee(items, fee):
    items.append(fee)

original = [3500, 8000]
alias = original
copy = original.copy()
add_fee(alias, 500)
print(original)
print(copy)

nested = [[1], [2]]
shallow = nested.copy()
shallow[0].append(9)
print(nested)

예상 결과는 다음과 같습니다.

[3500, 8000, 500]
[3500, 8000]
[[1, 9], [2]]

대입·얕은 복사·깊은 복사

alias = original은 같은 리스트를 가리키는 이름을 하나 더 만듭니다. copy()는 바깥 리스트를 새로 만들지만 내부 항목의 객체는 공유하는 얕은 복사입니다. 중첩 예제에서 안쪽 리스트가 같이 바뀌는 이유입니다.

copy.deepcopy는 내부 구조를 재귀적으로 복사하는 데 사용할 수 있으나 파일·연결·공유가 필요한 객체까지 무조건 독립 복제하는 만능 해결책은 아닙니다. 변경해야 하는 범위만 새로 구성하거나 불변 데이터 구조를 선택하는 편이 계약을 명확히 할 수 있습니다.

함수 계약에 변경 여부 드러내기

함수가 입력 리스트를 바꾸는지 문서와 이름에서 알 수 있게 합니다. 원본을 유지하는 함수라면 새 리스트를 반환하는 구현으로 바꿀 수 있습니다. 결과와 부수 효과를 모두 시험하지 않으면 반환값이 맞아도 원본 손상을 놓칠 수 있습니다.

  1. add_fee(copy, 100)을 호출해 original에는 100이 추가되지 않는지 확인합니다.
  2. 함수 안의 append를 items = items + [fee]로 바꾸면 외부 리스트가 그대로인지 확인합니다.
  3. 원래 코드로 되돌리고 바깥 객체와 내부 객체의 공유를 각각 설명합니다.
같은 카테고리의 다른 글
Python 강좌 / 함수 정의하고 값 반환하기

Python 강좌 / 함수 정의하고 값 반환하기

def·매개변수·return으로 계산 함수를 작성합니다. 출력과 반환의 차이, 함수 책임과 입력 전제, 호출 오류의 확인 방법을 설명합니다.

Python 강좌 / 가상환경 만들기와 pip로 패키지 관리하기

Python 강좌 / 가상환경 만들기와 pip로 패키지 관리하기

venv로 프로젝트 환경을 분리하고 python -m pip로 패키지를 관리합니다. 활성화, 버전 기록, 재설치와 설치 환경 불일치 해결 기준을 익힙니다.

Python 강좌 / 리스트 만들고 항목 추가·수정·삭제하기

Python 강좌 / 리스트 만들고 항목 추가·수정·삭제하기

리스트의 추가·수정·삭제와 정렬을 실행 예제로 확인합니다. sort와 sorted, 얕은 복사, 빈 목록과 반복 중 변경의 차이를 설명합니다.

Python 강좌 / macOS·Ubuntu에서 Python 실행 환경 준비하기

Python 강좌 / macOS·Ubuntu에서 Python 실행 환경 준비하기

macOS와 Ubuntu의 Python 설치 경로를 확인하고 개발용 가상환경을 만듭니다. 시스템 Python 보호, 배포판 버전 차이와 설치 오류의 확인 기준을 함께 다룹니다.

Python 강좌 / 비교·논리 연산자와 참·거짓 판단하기

Python 강좌 / 비교·논리 연산자와 참·거짓 판단하기

비교·논리 연산자와 참·거짓 변환을 설명합니다. and·or의 단락 평가, 0과 None의 차이, ==와 is의 용도를 예제로 확인합니다.

Python 강좌 / for·range·enumerate·zip으로 반복하기

Python 강좌 / for·range·enumerate·zip으로 반복하기

for·range·enumerate·zip의 용도를 비교합니다. 번호와 지출 항목을 함께 출력하며 범위의 끝 제외, zip의 길이 불일치와 반복 중 변경 문제를 확인합니다.

Python 강좌 / 가변 인수와 언패킹: *args·**kwargs

Python 강좌 / 가변 인수와 언패킹: *args·**kwargs

*args·**kwargs의 수집과 호출 시 언패킹을 비교합니다. 금액 합산과 옵션 출력 예제로 중복 인수, 문자열 펼치기와 인터페이스 설계 기준을 설명합니다.

Python 강좌 / 튜플과 시퀀스 언패킹 이해하기

Python 강좌 / 튜플과 시퀀스 언패킹 이해하기

튜플 생성과 언패킹, 별표 수집과 값 교환을 익힙니다. 불변성의 범위와 항목 수 오류, 리스트·딕셔너리와의 선택 기준을 설명합니다.

Python 강좌 / Python이란? 특징과 활용 분야

Python 강좌 / Python이란? 특징과 활용 분야

Python의 역할과 활용 범위를 이해하고 소스 파일·터미널·인터프리터를 구분합니다. 간단한 합산 예제를 실행하며 강좌의 실습 방식을 익힐 수 있습니다.

Python 강좌 / 리스트·딕셔너리·집합 컴프리헨션 사용하기

Python 강좌 / 리스트·딕셔너리·집합 컴프리헨션 사용하기

리스트·딕셔너리·집합 컴프리헨션의 변환과 필터를 비교합니다. 중복 키, 빈 결과와 부수 효과를 확인하며 일반 반복문과의 선택 기준을 익힙니다.