본문 바로가기

파이썬

자료형(Data Type) (3) - 튜플, 불(bool)

1. 자료구조(data structure)

파이썬에서 자료(data)들을 저장하는 여러 가지 구조들이 있으며, 이를 자료구조 또는 데이터구조라고 부른다.

■ 파이썬의 가장 기초적인 자료구조는 시퀀스(sequence)이다. 파이썬은 6개의 내장 시퀀스 str, bytes, bytearray, list, tuple, range를 가지고 있다.

■ 시퀀스는 요소(element)로 구성되며, 요소 간에는 '순서'가 존재한다. 각 요소는 인덱스(index)라는 고유한 번호를 부여받기 때문에 인덱스를 통해 요소에 접근할 수 있다.

■ 그리고 시퀀스에 속하는 자료구조들은 동일한 연산을 지원한다. 인덱싱(indexing), 슬라이싱(slicing), 덧셈 연산, 곱셈 연산 등이 이에 해당한다. 

■ 또한, 파이썬의 내장 함수 중 len() 함수를 통해 시퀀스의 길이를, min()과 max() 함수를 통해 시퀀스 요소 중 최솟값과 최댓값을 반환할 수 있다. 이외에도 많은 내장 함수들을 시퀀스에 적용할 수 있다.



 

2. 튜플

■ 튜플은 몇 가지 점을 제외하면 리스트와 아주 유사하다. 튜플도 시퀀스이기 때문에 인덱싱, 슬라이싱 등 동일한 함수들이 지원된다.

■ 몇 가지 다른 점은 튜플은 ( )을 사용하여 정의된다는 점과 리스트는 요솟값의 생성, 삭제, 수정이 가능하지만 튜플은 요솟값을 바꿀 수 없다는 점이다.

■ 그래서 튜플은 리스트처럼 append, extend, insert 메서드가 존재하지 않으며, 요솟값을 직접 삭제하거나 변경할 수 없다.

■ 정수, 부동소수점, 문자열, 리스트, 튜플, 딕셔너리, 집합, 불(bool)은 모두 파이썬 객체이다.

■ 가변 객체인 리스트, 집합, 딕셔너리와는 다르게 불변 객체인 정수, 부동소수점, 튜플, 문자열, 불(bool)은 값이 변경되면 새로운 값을 보관하기 위해 신규 메모리 위치를 지정하고 객체를 참조하는 변수는 새로운 객체를 참조한다.

■ 즉, 튜플과 리스트의 가장 큰 차이는 요솟값을 변화시킬 수 있는지의 여부이다. 

■ 리스트는 요솟값의 변화가 가능하기 때문에 값을 변화시켜야 하는 경우라면 리스트를, 요솟값이 항상 변하지 않기를 원한다면 튜플을 사용하면 된다.


2.1 튜플을 만드는 방법

튜플을 만드는 방법은 다음과 같다.

튜플_이름 = (항목1, 항목2, ... )
튜플_이름 = 항목1, 항목2, 항목3, ...

■ 튜플을 정의할 때, 각 요소 뒤에 쉼표(,)를 붙여 요소들을 구분한다. 

- 비어 있는 튜플을 만드려면 다음과 같이 소괄호만 사용하면 된다.

tuple = ()

■ 단, 소괄호 ( )를 사용하여 정의할 때, 1개의 요소만을 가지더라도 아래와 같이 반드시 쉼표를 붙여야 한다.

tuple = (1, )

■ 그리고 다음과 같이 소괄호를 생략하고도 튜플을 정의할 수 있다.

tuple = 1, 2, 3

■ 다른 자료구조로부터 튜플을 생성하는 방법이 있다. 다른 자료구조를 받아서 튜플로 변환하는 함수인 tuple()을 사용하면 된다. 예를 들어 아래와 같이 리스트에 tuple() 함수를 적용하여 리스트를 튜플로 변환할 수 있다.

list1 = [1, 2, 3]
tuple1 = tuple(list1)
print(type(tuple1), tuple1)
```#결과#```
<class 'tuple'> (1, 2, 3)
````````````

cf) 반대로 튜플을 리스트로 변환하려면 튜플에 list() 함수를 적용하면 된다.


2.2 튜플 연산

2.2.1 튜플 더하기

■ 튜플은 변경 불가 객체이기 때문에 앞서 언급한 것처럼 튜플은 한번 생성되면 요소를 추가할 수도, 삭제할 수도 없다.

■ 하지만 더하기 연산자(혹은 할당 대입 연산자 +=를 이용하여 튜플에 다른 튜플을 추가하는 것은 가능하다. 이는 기존의 튜플을 변경하는 것이 아닌, 새로운 튜플을 생성하는 것이다.

t1 = (1, 2, 3)
t2 = ('a', 'b', 'c')
print(id(t1))
```#결과#```
2709692253184
````````````

t1 += t2
t1
print(id(t1))
```#결과#```
2709691717504
````````````

- id() 함수를 통해 객체의 주솟값을 확인했을 때, 주소가 달라지는 것을 확인할 수 있다.

2.2.2 튜플 인덱싱, 슬라이싱

■ 튜플도 문자열, 리스트와 마찬가지로 시퀀스 자료형에 속하므로, 다음과 같이 인덱싱과 슬라이싱이 가능하다.

t1[-1]
```#결과#```
'c'
````````````

t1[:3]
```#결과#```
(1, 2, 3)
````````````

2.2.3 튜플 곱하기

■ 튜플도 다음과 같이 * 연산자를 통해 튜플의 요소들을 반복할 수 있다.

t2*2
```#결과#```
('a', 'b', 'c', 'a', 'b', 'c')
````````````

2.2.4 튜플 길이

■ 튜플도 len() 함수를 사용하여 튜플 안의 요소들의 개수. 즉, 튜플의 길이를 확인할 수 있다.

len(t1)
```#결과#```
6
````````````

2.2.5 튜플 안에 변경 가능 객체가 저장되어 있는 경우

튜플도 다른 자료형을 요소로 저장할 수 있어서, 튜플 안에 변경 가능 객체가 저장될 수 있다.

예를 들어 아래와 같이 튜플에 리스트가 튜플의 요소로 저장되어 있는 경우, 튜플 자체는 변경 불가지만, 튜플 안의 리스트는 변경할 수 있다.

t1 = (1, 2, 3, [1, 'a', 2, 'b'])
t1 
```#결과#```
(1, 2, 3, [1, 'a', 2, 'b'])
````````````

t1[1] = 2  # 튜플 자체는 변경 불가
```#결과#```
TypeError: 'tuple' object does not support item assignment
````````````

t1[-1][1] = 3
t1[-1][-1] = 10
t1 
```#결과#```
(1, 2, 3, [1, 3, 2, 10])
````````````

- t[1] = 2로 튜플의 요소 재할당. 즉, 튜플은 한 번 만든 뒤에 내부 요소를 다른 객체로 교체하는 것이 불가능한 것과

- 튜플 안에 가변 객체인 리스트의 내부 요소는 수정이 가능한 것을 확인할 수 있다.

cf) += 연산자를 이용해서 튜플의 요소를 리스트에 추가할 수 있다.

list1 = [1, 2, 3]
tuple1 = (10, 20)

list1 += tuple1
list1
```#결과#```
[1, 2, 3, 10, 20]
````````````

2.3 튜플의 패킹(packing)과 언패킹(unpacking)

■ 2.1에서 본 것처럼 소괄호를 이용하거나 소괄호를 생략해서 다음과 같이  튜플을 생성할 수 있다고 하였다.

튜플_이름 = (항목1, 항목2, ... )
튜플_이름 = 항목1, 항목2, 항목3, ...

■ 위의 구조를 보면 마치 여러 개의 데이터(항목1, 항목2, 항목3, ...)가 하나의 변수(튜플_이름) 안으로 압축되는 것처럼 보인다. 이것을 튜플 패킹(packing)이라고 한다.

■ 중요한 것은 이를 반대로 할 수도 있다는 점이다. 즉, 하나의 튜플 안에 저장된 데이터를 풀어서 다음과 같이 개별 변수에 저장할 수 있다. 이것을 튜플 언패킹(unpacking)이라고 한다.

(변수1, 변수2, 변수3, ...) = 튜플_이름
변수1, 변수2, 변수3, ... = 튜플_이름
## 튜플 패킹
t1 = 1, 2, 3
t2 = ('a', 'b')

## 튜플 언패킹
s1, s2, s3 = t1
print(s1, s2, s3)
```#결과#```
1 2 3
````````````

(c1, c2) = t2
print(c1, c2)
```#결과#```
a b
````````````

■ 또한, 서로 다른 자료형에 대해서도 패킹과 언패킹이 가능하다.

t3 = True, 10, 1.2, [1, 2, 3] # 패킹
v1, v2, v3, v4 = t3 # 언패킹
print(v1, v2, v3, v4)
```#결과#```
True 10 1.2 [1, 2, 3]
````````````

■ 이러한 패킹과 언패킹을 이용하여 아래와 같이 데이터의 순서를 바꿀 수도 있다.

n1, n2 = 10, 20
print(n1, n2)
```#결과#```
10 20
````````````

n1, n2 = n2, n1
print(n1, n2)
```#결과#```
20 10
````````````


 

3. 불(bool)

■ 불(bool) 자료형은 참(True)과 거짓(False)을 나타내는 자료형이다. 즉, True와 False. 2가지 값만을 가질 수 있다.


3.1 불리언(boolean) 값 생성

■ 불리언 값을 생성하는 방법은 간단하다. 다음과 같이 변수에 True 혹은 False를 할당하면 된다.

print(type(a), a)
print(type(b), b)
```#결과#```
<class 'bool'> True
<class 'bool'> False
````````````

3.1 자료형의 참과 거짓

■ 문자열, 리스트, 튜플, 딕셔너리 등의 값이 비어 있으면 거짓이 되고 공백이 아니면 참이 된다. 숫자에서는 값이 0일 때 거짓이 된다. 

string1 = "" # 공백 문자열
list1 = [] # 공백 리스트
tuple1 = () # 공백 튜플
dict1 = {} # 공백 딕셔너리
integer1 = 0

 

■ 예를 들어 다음과 같이 while문을 이용하여 a = [1, 2, 3, 4]라는 리스트가 공백 리스트가 될 때까지 pop 메서드를 적용한다고 했을 때

a = [1, 2, 3, 4]

while a:
    print(a.pop())

■ while 조건문:이 while a:이므로 리스트 a 내부에 값이 비어 있지 않으면 참(True)가 유지된다. 그러므로 공백 리스트가 되기 전 까지는 a.pop() 이라는 문장이 실행된다. 

■ 더 이상 리스트 a 내부에서 꺼낼 요소가 없으면 리스트 a는 공백 리스트가 되기 때문에 while 조건문=Flase:가 된다. 즉, While 문에서 조건문이 거짓이 되므로 while문이 종료된다.


3.2 불 연산

■ bool 함수를 사용하면 다음과 같이 자료형의 참과 거짓을 확인할 수 있다.

string1 = "" # 공백 문자열
list1 = [] # 공백 리스트
tuple1 = () # 공백 튜플
dict1 = {} # 공백 딕셔너리
integer1 = 0

print(bool(string1))
print(bool(list1))
print(bool(tuple1))
print(bool(dict1))
print(bool(integer1))
```#결과#```
False
False
False
False
False
````````````
string2 = "a" 
list2 = [1, 2] 
tuple2 = (1, ) 
dict2 = {} 
dict2['k'] = 'v'
integer2 = 1

print(bool(string2))
print(bool(list2))
print(bool(tuple2))
print(bool(dict2))
print(bool(integer2))
```#결과#```
True
True
True
True
True
````````````