아마 함수가 궁금하여 이 글을 들어오셨을 듯 한데, 이글을 읽기전 반드시 알아야 할 개념을 강제로 보여드리겠다.
- 참조 값 : 객체가 메모리를 생성했을 떄 메모리와 연결된 유일한 숫자 값이다. 즉, 메모리에 저장된 객체의 유일한 숫자갑이 객체의 주소가 된다. 만약 컴퓨터가 동일한 객체를 불러온다 했을 때, 이 객체의 주소로 동일한 객체에 해당하는 값을 찾아온다.
만약 기존의 객체 값을 어떤 함수를 이용해서 10을 곱하는 함수를 만들고 싶다고 하자.
여기서 기존의 객체 값은 k이며, 1이 대입되어 있다.
k = 1
def modify(n) :
n = n * 10
return(n)
# modify(k) 결과 : 10
# k 결과 : 1
위의 함수에서 우리는 당연히 modify 함수 인자에 k가 삽입되면 modify(k) 결과는 10, k결과도 10이 예상되었을 것이다. (왜냐? k를 함수에 대입하면 k=k*10 이기 때문) 하지만 위와 같이 결과가 다르게 나온다. 왜 일까?
k값이 바뀌지 못한 원인
거의 모든 현대적인 프로그래밍 언어에서는 혼란을 막기 위해 변수의 값만이 전달된다. 이를 값에 의한 호출(call-by-value) = 값에 의한 전달(pass - by - value)이라 부른다. 위 예시에서 변수 k가 modify함수의 영향을 받지 않는 것 또한 값에 의한 호출을 받았기 때문이다. 이는 k에 숫자나 문자열을 대입해도 마찬가지인데, 이는 숫자나 문자열이 변경 불가능한 객체(immutable object)이기 때문이다. 만약, 숫자나 문자열을 변경하게 되면 새로운 객체가 생성된다.
위 예시로 다시 정리해보면 순서는 이렇다.
k에 문자나 숫자 대입(변경 불가능한 개체) ▶ 함수 modify(k) 실행하나, 변경 불가능한 개체인 k의 변수 값은 바뀌지 못함 ▶ k값 호출시 처음 대입된 문자나 숫자 호출
변경 불가능한 개체가 바뀌지 않음을 참조 값으로 증명 해보자.
python에서 변수의 참조 값을 볼 수 있는 함수인 id()를 이용할 것이다. 아래 결과 값들을 보면 같은 msg 임에도 불구하고 각 참조 값이 다른 것을 확인할 수 있다. 참조 값이 다르다는 것은, 객체의 주소가 다르다는 것과 같으므로, 같은 변수 이름이여도 서로 다른 메모리 위치에 할당 되었다는 것을 알 수 있다.
msg = "I love"
id(msg)
# 결과 값 : 2961446324976
msg += "you"
id(msg)
# 결과 값 : 2961446327344
변경 가능한 개체일 경우의 참조 값은 어떨까?
리스트는 변경 가능 객체(mutable object) 중 하나이다. 이를 전달하면 어떻게 될까? 기존 ex_list 변수가 바뀐 형태로 출력된다.
def modify2(a) :
a += [3,4,5]
ex_list = [1,2]
print(ex_list) # 기존 리스트 값 출력 : [1,2]
modify2(ex_list) # ex_list에 함수 적용
print(ex_list) # 기존 리스트 값 출력 : [1,2,3,4,5] => 값이 바뀜
그렇다면 참조 값은 어떨까? 예상대로 동일한 참조 값을 가짐을 알 수 있다.
ex_list = [1,2]
id(ex_list) # 참조 값 : 2961446341448
modify2(ex_list)
id(ex_list) # 참조 값 : 2961446341448
리스트의 경우 리스트의 참조값이 전달되며 함수에서 참조 값을 이용해 리스트 변경시 언제든 변경이 가능하다. 따라서 새로운 객체 생성 없이 기존의 객체가 변경된다. 중요한 사항이니 반드시 기억해 두자.
지역 변수와 전역변수
지역(local) 변수는 함수 안에서 선언된 변수, 전역(global) 변수는 함수 외부에서 선언된 변수이다.
즉, 함수를 기준으로 안(local)과 밖(global)을 나누어 이름을 붙인 것이다. 예는 아래와 같다.
k = 1 # 전역 변수 k
def modify(n) :
n = n * 10 # 지역변수 n
return(n)
지역변수
지역 변수는 함수가 호출될 때 생성되고 함수가 종료되면 소멸되어서 더 이상 사용이 불가하다.
= 함수 안에서만 사용이 가능하다는 의미, 함수 종료되면 호출해도 NameError : Name '' is not defined 를 뱉으며 호출이 불가능하다. 또한 매개변수도 지역변수의 일종이다.
이렇듯, 어느 특정 영역안에서만 사용 가능한 변수를 변수의 영역(scope)라고 부른다.
전역변수
함수 외부에 정의된 변수를 전역 변수(global valiable)이라 부른다. Python에서의 전역 변수를 다루는 방식은 타 언어와는 많이 다르다. Python 인터프리터는 어떤 함수를 실행시킬 때 함수 내 변수를 우선 지역변수에서 찾고 ▶ 전역변수에서 찾는다. 이 순서를 꼭 기억해야 한다.
s = "나는 전역변수"
def vartest() :
s = "나는 지역변수"
print(s)
vartest() # 나는 지역변수 출력
print(s) # 나는 전역변수 출력
지역 변수와 전역 변수의 관계
하나의 변수가 전역변수가 되었다가 지역변수가 될 순 없다.
def sub() :
print(s)
s = '나는 지역변수'
print(s)
s = '나는 전역 변수'
sub()
print(s)
오류 순서
1. def 함수를 읽는다. > sub함수를 생성한다.
2. s 개체에 값을 대입한다.
3. sub()함수를 실행한다. > 오류 발생한다. > 실행을 멈춘다.
4. sub()함수내 오류 원인을 찾는다 > print(s)가 오류 원인임을 찾았다. 오류 내용 : local variable 's' referenced before assignment
전역 변수 s로 앞서 선언되었기 때문에 파이썬 인터프리터가 함수 안에서 s 변수를 지역 변수로 인식을 못하기 때문에 발생한 문제이다. 즉, 지역 변수로 지정전에 print(s)를 해버리니 오류가 발생한 것이다.
이를 해결하기 위해서는 전역 변수를 사용하겠다는 global() 옵션을 s에 부여 해야 한다.
def sub() :
global s
print(s)
s = '나는 지역변수'
print(s)
s = '나는 전역변수'
sub() # 나는 전역변수, 나는 지역변수 차례로 출력
print(s) # 나는 지역변수 출력
여러 개의 값 반환하기
Python을 제외한 다른 프로그래밍 언어는 함수가 항상 하나의 값 만을 반환한다. Python에서는 함수가 하나 이상의 값도 반환이 가능하다.
def sub() :
return 1,2,3
a,b,c = sub()
print(a,b,c) # a=1, b=2, c=3이 반환된다.
저장하는 순서는 다음과 같다.
1. 함수에서 return을 하면 (1,2,3)의 튜플 형태로 반환한다. 즉, 튜플이 기본이다.
2. 이 튜플의 값 하나하나를 a,b,c에 각각 대입한다.
만약 튜플 형태로 반환하기 싫다면 return 1,2,3 값에 []를 양 옆에 씌워주어 리스트 형태로 만든다.
def sub() :
return [1,2,3]
ex = sub()
ex # 결과식 : [1,2,3]
'Python > Coding Base' 카테고리의 다른 글
12. 리스트(List) 1 - 리스트와 시퀀스(sequence) (0) | 2022.01.23 |
---|---|
11. 함수(function) 4 - 람다식(무명 함수), 모듈 (0) | 2022.01.23 |
9. 함수(function) 2 - 디폴트 인수, 키워드 인수 (0) | 2022.01.23 |
8. 함수(function) 1 - 인수, 매개변수, 반환 값 (0) | 2022.01.18 |
7. 반복문(Iteration) - while문 (0) | 2022.01.13 |