시작에 앞서서 파이썬은 모든 것이 객체이다.
파이썬에서 변수를 할당하는 작업은 해당 객체에 대해 참조를 한다는 의미이다.
== 는 값을 비교하는 연산자
is 는 객체의 id() 값을 비교하는 연산자.
id()함수는 객체의 고유값을 리턴한다. 즉 어떤 객체를 가리키는지 알 수 있다.
id는 파이썬이 객체를 비교하기 위해 부여하는 일련번호 이다.
// C++
int a = 10;
int &b = a;
b = 7;
std::cout<<a<<std::endl;
결과: 7
b는 참조변수로서, b에 새로운 값을 할당하면 원래 변수인 a 또한 그 값으로 바뀐다.
>>> a = 10
>>> b = a
>>> id(a), id(b) #referencing using assignment operator
(1234556, 1234556)
>>> b = 7
>>> a, id(a), id(b)
(10, 1234556, 1333345)
처음에 b=a를 할때까지만 해도, a 와 b는 동일한 객체를 가리키며 참조관계이다. 그렇지만, b에 7을 assign 하는 순간 b는 더이상 a와 참조관계가 아니게 된다.
7은 불변객체이어서 참조변수로 값 자체를 조작할 수 없어서 이런 결과가 나오지만, 가변객체인 list를 사용하게 되면 사뭇 다른 결과가 나온다. 이 경우에서는 c++와 마찬가지로 참조변수로 객체를 조작하게 되면 원래변수에도 그 조작의 결과가 나타나게 된다.
>>> a = [1, 2, 3]
>>> b = a
>>> b[2] = 5
>>> a
[1, 5, 3]
그렇지만 이런 경우에도 assignment operator를 이용해서 다른 list를 b에 넣는다면 참조관계가 깨진다.
나무위키 왈)
함수의 매개 변수로 불변 객체를 넘겼냐 가변 객체를 넘겼냐에 따라서 함수 바깥에 있는 인자의 값도 수정할 수 있는지 없는지가 달라진다. 불변 객체를 넘겼으면 값의 복사만 일어나고 함수 바깥에는 영향을 주지 못하므로'값에 의한 호출(Call by Value)'이 될 것이며, 가변 객체를 넘겼으면 함수 바깥에까지 영향을 줄 수 있으므로 '참조에 의한 호출(Call by Reference)'이 될 것이다.
파이썬 공식 문서에서는 파이썬의 인자 전달 방식을 '할당에 의한 호출(Call by Assignment)', 또는 '객체 참조에 의한 호출(Call by Object Reference)'이라고 명시하고 있다.
함수도 위의 원리가 적용된다.
def a_function(a):
#function_body
pass
라는 함수가 있다고 칠 때에, 매개변수 a에 변수를 전달한다는 것은 즉 a에 객체를 참조한다는 것이다.
만약 그 객체가 불변이라면, #function body에서 a를 조작하는 것은 함수 바깥에 영향을 주지 못한다.
만약 그 객체가 가변이라면, #function body에서 a를 조작하는 것은 함수 바깥에 영향을 준다.
배열과 포인터 사이에 성립하는 정확한 규칙은 다음과 같다.
배열 타입을 갖는 수식(배열 이름 또한 여기에 해당한다)은 자동 변환되어, 그 배열의 첫 번째 원소를 가리키는 포인터 주소 값을 반환한다. 이 결과 값은 lvalue(메모리 상에 주소를 가진 =의 좌변 값)가 아니다. 단, sizeof 연산자의 피연산자로 쓰인 경우, & 연산자의 피연산자로 쓰인 경우, char 형 배열의 초기화에 쓰이는 문자열 상수인 경우는 그 예외이다.
말이 어렵지만, 요약하자면 마지막의 특수한 경우 빼고는 array는 배열의 첫 번째 원소를 가리키는 포인터 주소 값을 반환한다.
그리고 변수이름이 될 수 없다.