2021년 8월 8일 일요일

python 함수 인자의 전달 call by reference

C/C++ 언어를 많이 사용하다가 python 언어를 사용하게 되면 답답해 하는 부분이 바로 pointer입니다. 

그러면 왜 pointer를 사용하게 되었을까? 생각해본적이 있나요?


***


책에 나와있는 부분도 아니고 정답이 있는 것은 아닙니다. 

생각해보자면, 사용하고자 하는 함수에서 인자로 포인터를 원했기 때문일겁니다. 그러면 많은 함수들이 왜 포인터 변수를 원했을까요? 그것은 속도와 효율성의 문제 입니다.

기본적으로 C/C++ 언어 함수는 call by value로 동작합니다. 이말은 호출된 함수안에서 어떤 변수를 건들더라도 호출되기전의 변수가 변경되지 않는 동작을 의미합니다. 이는 현대에 와서는 당연한것으로 받아들여지지만 오래전 언어에서는 안그런 경우도 있었습니다.

strlen() 이란 함수를 보자면 char *를 인자로 가지고 있습니다. 만약 여기 인자에 char *가 아닌 문자열을 다루는 char a[100] 짜리 array가 통째로 전달된다면 함수 호출시 변수에 모든 값이 복사가 되어 전달되어야 합니다. 주소를 전달하는것보다는 무척 비효율 적이겠죠.

다시 python언어로 돌아와서, python에서도 기본적으로 call by value로 전달합니다. 그렇다면 reference로 전달하려면 어떻게 해야할까요?

답은 변수중 다른 형태의 변수를 저장할 수 있는 값을 전달하는것입니다. 이 부분은 pointer 의 개념과 같습니다. 그래서 그런 변수가 어떤것이 있느냐 바로 list와 dictionary 타입 입니다.

python에서 모든 객체는 아이덴티티(identity), 형(type), 값(value)을 갖습니다. 

identity값을 출력하기 위해서는 id() 함수를 사용하면 되며 id가 같은 경우 같은 class(변수)라고 보면 됩니다.

id를 출력해가며 어떻게 변수가 전달되는지 예제로 만들었습니다.


print("call by value")

a = 100
print(id(a),type(a),a)

b = a
print(id(b),type(b),b)

def fun_a(c):
	print(id(c),type(c),c)
	c = 200
	print(id(c),type(c),c)

fun_a(b)
print(id(b),type(b),b)



print("call by reference")
a = [100]
print(id(a),type(a),a)

b = a
print(id(b),type(b),b)

def fun_a(c):
	print(id(c),type(c),c)
	c = 200
	print(id(c),type(c),c)

def fun_b(c):
	print(id(c),type(c),c)
	c[0] = 200
	print(id(c),type(c),c)

fun_a(b)
print(id(b),type(b),b)
fun_b(b)
print(id(b),type(b),b)


결과

call by value
140714474676992 <class 'int'> 100
140714474676992 <class 'int'> 100
140714474676992 <class 'int'> 100
140714474680192 <class 'int'> 200
140714474676992 <class 'int'> 100
call by reference
2054172649856 <class 'list'> [100]
2054172649856 <class 'list'> [100]
2054172649856 <class 'list'> [100]
140714474680192 <class 'int'> 200
2054172649856 <class 'list'> [100]
2054172649856 <class 'list'> [100]
2054172649856 <class 'list'> [200]
2054172649856 <class 'list'> [200]




댓글 없음:

댓글 쓰기