본문 바로가기

Language/Python

RePythonOOP 11일차 Python Packing VS Unpacking, Mutable(가변) VS Immutable(불변), sort() VS sorted()

PAINTING MARCH 1985

Insight

1. '모든 것이 객체이다.' == '순수 객체지향 언어이다'. 가 같은 말이라는 것을 알게 되었다.

2.  패킹과 언패킹으로 인자를 전달하고 값을 할당하는 것을 알게 되었다.

3. mutable과 immutable에 있는 call by ~~~~ 들을  구분하여 말할 수 있다.

4. sort와 sorted 가 본인 스스로 자주 사용해 왔엇는데 조금 더 자세히 들여다 보았다. 

 

Tuple Packing VS Unpacking

패킹      : 여러개의 객체를 묶어서 자료형으로 선언 해 주는 것이다.

언패킹  : 여려개의 객체가 들어 간 자료 형을 *로 풀어주는 것이다. (가변 파라미터 *,키워드 파라미터 ** 의 개념과 같다)

 

 

예를 들어보자.

divmod(a,b) a를 b로 나누는 함수이고 결과는 몫과 나머지로 return한다.

# a,b를 넣어줘도 되고
print(divmod(100, 6))    # (16, 4)
# 튜플자체를 씌운 자료형을 *를 붙여줌으로 언패킹을한다.   
print(divmod(*(100, 6))) # (16, 4)

# 이런식으로도 사용가능하다.
i, j, *k = range(10)

# 함수에서 가변 파라미터는 리스트와 튜플을 받을수 있지만.
# 기본형으로 k는 리스트로 반환한다.
print(i, j , k) # 0 1 [2, 3, 4, 5, 6, 7, 8, 9] 

# 일단 받고 튜플로 k를 바꾸어 주어도 된다.
i, j, *k = range(10)
print(i, j , tuple(k)) # 0 1 (2, 3, 4, 5, 6, 7, 8, 9)

 

Mutable(가변) vs Immutable(불변)

기본적으로 Mutable은 같은 주소(id)에서 값이 변경 가능하므로 얕은 복사가 진행 될 수도 있다.

Immutable은 내부의 값들이 변경이 불가능하 므로 자료 공간을 재 배정함으로 얕은 복사가 일어 나지 않는다.

(무조건 깊은 복사가 일어난다)

 

Immutable : 상수, 문자열, 튜플 자료형

Mutable  : 그외 모든 객체

 

함수의 매개변수로 Mutable을 넘기느냐 Immutable 넘기느냐에 따라 다르다.

 

값에 의한 호출(Call by Value)

함수에 변경 불가능한(Immutable) 객체의 값을 수정할 때는 바뀐 값이 저장된 새로운 객체를 생성하고 해당 객체를 참조한다.

 = > 이러한 이유로 파이썬은 순수 객체지향 언어라고 할 수 있다.

 

참조에 의한 호출(Call by Reference ) == 할당에 의한 호출(Call by Assignment) == 객체 참조에 의한 호출(Call by Object Reference)

함수에 변경 가능한(Mutable) 객체를 넘겼으면 함수 바깥에까지 영향을 줄 수 있다.

 

더 자세한 내용은 여기에 있다 :https://testspoon.tistory.com/172?category=726985

 

OOP 5일차 중간 파이썬에서 파라미터와 인자는 왜 구분 하는 걸까? (파이썬에서 파라미터의 기본값은 클래스의 인스턴스화에 어떤 영향을 끼치는가 ?)

이 글은 파라미터, 인자의 구분까지 아신다고 가정하에 작성되었습니다. 그냥 구분을 하는것 보다 왜 왜 구분지어 부르는지에 대해 파헤치는 글입니다. Insight 파라미터에 기본값(mutable)을 지정한 클래스의 인..

testspoon.tistory.com

 

이러한 모든 것이 객체로 이루어져 있으므로 이유로 파이썬은 순수 객체지향 언어라고 할 수 있다.

 

 

튜플(Immutable)과 리스트(mutable)를 예를 들면서  어떠한 호출이 일어나는 가에 대해 알아보자

tuple_ = (10, 15, 20)
list_ = [10, 15, 20]

print('tuple', tuple_, id(tuple_)) # tuple (10, 15, 20) 140312517195888
print('list', list_, id(list_))  # list [10, 15, 20] 140312516811664


tuple_ = tuple_ * 2
# 일반 대입 산술 연산자시 깊은 복사
list_ = list_ * 2

print('tuple', tuple_, id(tuple_)) # tuple (10, 15, 20, 10, 15, 20) 140312517351584
print('list', list_, id(list_))  # list [10, 15, 20, 10, 15, 20] 140312516811104


tuple_ *= 2
# 할당 연산자 (+= *=) 사용시 얕은 복사가가 일어난다.  
list_ *= 2

print('tuple', tuple_, id(tuple_)) # tuple (10, 15, 20, 10, 15, 20, 10, 15, 20, 10, 15, 20) 140312517714640
print('list', list_, id(list_))  # list [10, 15, 20, 10, 15, 20, 10, 15, 20, 10, 15, 20] 140312516811104

# 그러므로 사용자의 의도에 맞게 가변형 자료형(특히 리스트)을 사용할 때는 주의를 해야한다.

 

sort() vs sorted()

sort : 정렬 후 객체 직접 변경

sorted : 정렬 후 새로운 객체(새로운 id) 반환

                 두 함수가 공유 하는 옵션 : reverse = True 거꾸로 값을 반환

                  key = 내장 함수 기준으로 정렬(len[길이별],lambda,str.upper등)

 

 

sorted : 정렬 후 새로운 객체 반환 (원본의 객체가 변환되지 않음)

깊은 복사의 개념

 

예시를 보자

 

sorted_ = ['6','3','7','4','7','22','1','0','20']

print('sorted()', sorted(sorted_))              # sorted() ['0', '1', '20', '22', '3', '4', '6', '7', '7']
print('reverse', sorted(sorted_, reverse=True)) # reverse ['7', '7', '6', '4', '3', '22', '20', '1', '0']
print('key=len', sorted(sorted_, key=len))      # key=len ['6', '3', '7', '4', '7', '1', '0', '22', '20']
print('key=lambda', sorted(sorted_, key=lambda x: x[-1])) # key=lambda ['0', '20', '1', '22', '3', '4', '6', '7', '7']
print('key=lambda, reverse', sorted(sorted_, key=lambda x: x[-1], reverse=True)) # key=lambda, reverse ['7', '7', '6', '4', '3', '22', '1', '0', '20']
print('origin sorted_', sorted_) # origin sorted_ ['6', '3', '7', '4', '7', '22', '1', '0', '20']

 

sort : 정렬 후 원래의 객체 변경 되어짐

            sort()의 return은 None

            얕은 복사의 개념

 

sort_ = ['6','3','7','4','7','22','1','0','20']

print('sort_.sort(), sort_', sort_.sort(), sort_)           # sort_.sort(), sort_ None ['0', '1', '20', '22', '3', '4', '6', '7', '7']
print('reverse=True', sort_.sort(reverse=True), sort_)      # reverse=True None ['7', '7', '6', '4', '3', '22', '20', '1', '0']
print('key=len', sort_.sort(key=len), sort_)                # key=len None ['7', '7', '6', '4', '3', '1', '0', '22', '20']
print('key=lambda', sort_.sort(key=lambda x: x[-1]), sort_) # key=lambda None ['0', '20', '1', '22', '3', '4', '6', '7', '7']
print('key=lambda, reverse', sort_.sort(key=lambda x: x[-1], reverse=True), sort_) # key=lambda, reverse None ['7', '7', '6', '4', '3', '22', '1', '0', '20']