Python

newhyork·2022년 5월 5일
0

variable


  • 파이썬에서의 변수는, ‘값’ 자체를 가지고 있는 무언가가 아니다.
    그저 객체에 연결된 이름에 불과하다.
    즉, 변수는 ‘객체’를 ‘참조’하는 것이다.
    • 파이썬에서는 데이터, 함수, 모듈 등 모든 것을 객체로 취급한다.
      객체는 id(식별 번호)로 식별 되고, 자료형을 가지며, 메모리를 차지한다.
    • 파이썬의 대입 기호 ‘=’는 변수에 값 자체를 ‘복사’하는 것이 아니라,
      어떤 ‘값’을 가지는 객체에 대한 참조(식별 번호)를 ‘대입’하는 것이다.
  • 파이썬에서의 변수 선언 및 초기화, 할당(대입)
    ex. n = 17
  1. 좌변에 n이라는 변수는 처음 나와 선언되었고, 우변에 17이라는 값을 갖는 int형 객체가 생성된다.
    '='에 의해, 생성된 객체를 변수 n에 대입함에 따라 변수 n의 자료형도 자동으로 초기화된다.
    (이를 두고 편의상, 변수 n에 값이 할당되었다 내지는 값을 참조한다 라고 하곤 한다.)
  2. 이제 n과 17의 식별 번호는 같다.
  3. 여기서, n = 18.1로 값이 갱신될 시, 18.1이라는 값을 갖는 float형 객체가 생성된다.
    새로 생성된 이 객체의 식별 번호는 당연히 이전 것(17)과는 다르다.
  4. 이 객체를 변수n이 참조한다.
  5. n은 18.1의 식별 번호와 같아진다.
    • 따라서, 일반적으로 변수의 값이 변경되었다고 하는 것은, (즉, 참조하는 객체가 변경)
      값이 바뀌는 것이라고 하기보단 식별 번호가 바뀌는 것이라고 하는 게 더 정확하다.
      (대개 편의 상, 값이 바뀐다고 하긴 한다.)
      이러한 개념 하에서, 파이썬에서는 변수에 어떤 자료형이든 자유롭게 대입할 수 있는 것이다.
    • 다른 언어에서 변수란 값을 저장하는 상자라고 표현하는 것이, 파이썬에선 부정확하다.
  • 리스트 혹은 튜플 내 임의의 원소 x[n] 또한, 어떤 객체를 참조하는 변수일 뿐이다.
    따라서, 각 원소는 참조하는 객체에 따라 식별 번호를 갖는 것이다.

call by object reference


  • 파이썬에서는 매개변수에 '실제 인수'가 '대입'되는 방식이다. (’복사’가 아님)
    따라서 함수 실행 시점에서 매개변수가 참조하는 것(객체)은 인수가 참조하는 것(객체)과 같다.
    (이 말은, 파이썬에서의 변수는 값을 복사하여 할당하는 등의 방식이 아닌
    객체에 대한 참조를 대입하는 것이란 말의 연장선으로 볼 수 있다.)
    • 예를 들어 n=5가 있고 어떤 함수의 매개변수 x가 n을 인수로 취한다고 하였을 때,
      함수 실행 시점에서 n은 물론이고 x도 int형 객체인 5를 참조한다는 말이다.
  • 그리고 인수가 mutable이냐 immutable이냐에 따라,
    함수 안에서 매개변수의 값(참조하는 객체)을 변경 시,
    함수가 끝난 후 실제 인수의 값(참조하는 객체)이 변경될 수도 있다.
    함수 안에서 매개변수의 값을 변경 시, 인수의 자료형에 따른 구분은 다음과 같다.
    • immutable
      다른 객체를 생성하고, 매개변수는 그 객체에 대한 참조로 업데이트 된다.
      그래서 매개변수의 값을 변경해도 함수가 종료된 후 호출하는 쪽의 실제 인수에는 영향이 없다.
    • mutable
      객체 자체를 업데이트한다.
      그래서 매개변수의 값을 변경하면 호출하는 쪽의 실제 인수 값(참조하는 객체)이 변경된다.
  • 이러한 특징은,
    파이썬에서의 인수 전달이 실제 인수인 객체에 대한 '참조'를 값으로 전달하여
    매개변수에 '대입'하는 방식이기 때문이다.
    이를 call by object reference 라고 한다. (n이 5를 참조한다는 것을 x에 ‘대입’)
    • 다른 언어에서는 다음과 같은 방식을 사용하곤 한다.
      • call by value: 실제 인수의 '값'을 매개변수에 '복사' (x가 인수n의 '값'인 5를 복사)
      • call by reference: 실제 인수의 '참조'를 매개변수에 '복사'하여
        매개변수가 실제 인수와 같아짐 (n이 5를 참조한다는 것을 x에 ‘복사’)

== vs is


  • ==: 값이 같은지 비교한다.
  • is: 값을 물론이고 식별 번호까지 동일한 지 비교한다.
    즉, 같은 객체인지 비교한다.
  • 서로 같은 순서와 값으로 된 원소를 갖는 두 리스트가 따로 생성되었다면,
    ==으로 비교 시는 같겠지만 is로 비교 시에는 다르다고 판단한다.

shallow copy vs deep copy


  • shallow copy
    • ‘=’ 대입을 통한 얕은 복사
      • 만약 리스트B가, 리스트A를 ‘=’으로 대입한 것으로 (복사되어) 생성되었다면
        이는 값 자체의 복사가 아니라, 단순히 참조하는 곳이 복사된 것이다.
      • 즉, 리스트 A와 B의 id가 동일하여 서로 같은 객체에 대한 참조를 하는 것이므로,
        쉽게 말해 값을 공유한다.
        그래서 리스트 A의 원소 값을 바꾸면 리스트 B의 원소 값도 따라 바뀐다.
      • 곱셈으로 리스트를 생성할 경우도 이러한 얕은 복사에 해당된다.
        따라서, 필요에 따라 곱셈이 아니라 반복문으로 생성해주곤 한다.
    • copy 함수 및 메서드, [:] 슬라이싱을 통한 얕은 복사
      • 복사하여 생성된 리스트 객체의 id는 다르다.
      • 1차원적으로 보았을 때는 깊은 복사를 한 것처럼 보이나,
        내부에 리스트 등이 존재한다면 동일 객체를 참조하는 것이 된다.
      • 반복문을 통해 응용한다면 깊은 복사를 한 것처럼 구현할 순 있다.
  • deep copy
    • 리스트의 내부의 모든 것을 참조가 아니라 객체 자체 수준으로 복사하고자 한다면,
      copy.deepcopy()를 이용한다.
    • 매우 느리다는 단점이 있다.

0개의 댓글