[Python] 데이터 타입 - 1

이번 포스팅에서는

1. 파이썬의 기본 데이터 타입과 메모리 동작 원리를 이해하고

2. 각 타입의 특성 및 활용법을 학습 해보겠습니다.

 

파이썬의 데이터 타입은 크게 두가지로 나뉩니다.

 

Primitive (불변)

: int, float, bool, str, NoneType

: 값이 변경되면 새로운 객체가 생성되고 변수는 그 새로운 객체를 가리킵니다.

 

프리미티브 타입은 '고유한 값'을 가진 물건과 같습니다.

만약 20살에서 21살이 되었을 때, 20이라는 값이 없어지는게 아닌 이제 21이라는 새로운 나이, 즉 값을 가지게 된 것과 같습니다.

파이썬에서는 정수, 실수, 참/거짓, 문자열 등이 여기에 해당 합니다.

한 번 만들어지면 그 내용물을 직접 바꿀 수 없고 바꾸는 것처럼 보이는 건 사실 새로운 내용물을 만들어서

다른 곳에 두는 것과 같습니다.

 

Reference (대체로 가변)

: list, dict, set, tuple

: tuple은 불변이지만 내부 요소의 참조는 가변일 수 있기 때문에 참조형으로 분류 됩니다.

: 변수가 실제 데이터가 저장된 메모리 주소를 참조합니다.

 

레퍼런스 타입은 '주소록'이나 '지도'와 비슷합니다.

예를 들어

301동에 사는 주민 목록에 [철수, 영희, 민수]가 있다고 가정했을 때

이 목록 자체는 하나의 '주소'를 가지고 있고,

301동이라는 주소를 찾아가면 주민 목록 중 한 명을 만날 수 있습니다.

만약 여기서 철수가 수진이로 바뀐다고 가정하면

주민 목록의 주소는 그대로지만 주민이 바뀌어 내용이 바뀌었다고 할 수 있습니다.

여기에서의 핵심은 변수가 실제 값 대신 값이 있는 '주소'를 기억한다는 겁니다.

 

Primitive vs Reference

Primitive: 실제 값을 메모리에 저장(예: x= 10이면 10이라는 값 자체가 저장)

Reference: 값이 저장된 메모리 주소(위치)를 저장 (예: xyz = [1,2,3] 이면 [1,2,3] 리스트가 저장된 곳의 주소가 저장됨)

 

변수와 메모리의 동작원리를 알아보겠습니다.

변수는 메모리 주소를 가리키는 이름표 역할을 합니다.

1. x = 10: 메모리에 10 이라는 정수 객체가 생성됩니다.

2. x 는 이 10 객체의 메모리 주소를 가리킵니다.

3. y = x: y 또한 x 가 가리키는 동일한 메모리 주소를 참조하게 됩니다.

 * 여기서 id(x) 와 id(y)를 출력하면 같은 주소 값이 나옵니다.

 

Primitive 데이터 타입

 

Int 정수형

- 불변: 값을 변경하면 새로운 객체가 생성

- 무한 정밀도: 메모리가 허용하는 한 매우 큰 정수도 표현 가능

- 작은 정수 캐싱: -5부터 256까지의 정수는 파이썬 실행 시 미리 메모리에 올려두고 재사용하여 효율성을 높임

- 표현: 10진수 외에 2진수, 8진수, 16진수로 표현 가능

(0b는 2진수, 0o는 8진수, 0x는 16진수)

- int() 내장함수 (형 변환): 문자열, 실수, 진법 문자열을 정수로 변환할 때 사용

* "123" -> int("123") => 123

* 12.9 -> int(12.9) => 12 (소수점 아래는 반올림이 아니라 버림)

* "1010" -> int("1010", 2) => 2진수로 해석하여 숫자 10 (두번째 문자열 2는 2진수라고 알려주는 역할)

 

float 실수형

- IEEE 754 표준: 컴퓨터가 실수를 표현하는 국제 표준인 64비트 부동소수점 방식으로 저장

- 정밀도 한계: 약 15~17자리의 정밀도를 가짐

* 컴퓨터는 모든 실수를 100% 정확하게 표현하기 어렵습니다. 특히 0.1 같은 숫자는 2진수로 바꾸면 무한히 반복되는 소수가 되는데, 컴퓨터는 정해진 공간(64비트)에만 저장해야 하기때문에 중간에 잘라낼 수 밖에 없습니다. 이 때문에 0.1 + 0.2 를 계산하면 정확히 0.3이 아닌 0.300....04 같은 미세한 오차가 발생할 수 있습니다. 만약 두 실수가 같은지 비교하고 싶을 땐 == 연산자 대신 math.isclose() 같은 함수를 사용하는 것이 안전합니다. 이 함수는 '두 숫자가 거의 같다면 같다' 라고 판단해줍니다!

- 특수 값: inf (무한대), -inf(음의 무한대), nan(Not a Number) 등을 표현할 수 있음

 

내장 수학 함수

파이썬에 기본으로 포함되어 있어 import 없이 바로 사용할 수 있습니다.

 

- abs(x): Absolute의 약자, 절댓값 (-5의 절댓값은 5, 3.7의 절댓값은 3.7. 항상 양수로 만들어주는 함수)

- pow(x, y) 또는 x ** y : x의 y 거듭제곱

- round(x, n) : x를 소수점 n 자리까지 반올림. n을 생략하면 정수로 반올림.

 

Math 모듈

복잡한 수학 연산을 위해 import math를 통해 불러와야 하는 모듈

 

- 제곱근 & 거듭제곱

: math.sqrt(x): x의 제곱근

: math.pow(x, y): x의 y 거듭제곱 (내장 pow와 동일하지만 실수 결과를 반환)

- 올림, 내림, 버림

: math.ceil(x): Ceiling의 약자. x보다 크거나 같은 가장 작은 정수(올림)

: math.floor(x): x보다 작거나 같은 가장 큰 정수(내림)

: math.trunc(x): Truncate의 약자. x의 소수점 이하를 버리고 정수 부분만 반환.

* floor와 비슷해보이지만, 음수일 때는 결과가 달라짐 (math.floor(-3.2)는 -4, math.trunc(-3.2)는 -3)

-기타 함수

: gcd(), lcm(), log(), exp(), sin(), cos(), tan(), math.pi, math.e(자연 상수 e) 등

 

 

str 문자열

- 불변: 한 번 생성된 문자열은 수정 불가(수정처럼 보이는 작업은 새 문자열 생성)

- 순서 보장: 각 문자가 고유한 위치(인덱스)를 가짐

- 유니코드 지원: 전 세계의 다양한 문자 표현 가능

- 접근 및 슬라이싱: 마치 배열처럼 특정 위치의 글자를 가져오거나, 일부분만 잘라서 가져올 수 있음

- 자주 쓰는 메서드

: find(sub) : 특정 문자열이 어디에 있는지 찾아줌

: rstrip(): 문자열 오른쪽의 공백 제거 

: split(sep): 특정 구분자를 기준으로 문자열을 여러 조각으로 나눠서 리스트로 만들어줌.

: 이 외에도 replace(), upper(), lower(), startswith(), endswith() 등 

 

 

bool 불린형

- True 또는 False 두 가지 값만 가짐

- 정수처럼 연산 가능(True = 1, False = 0 으로 간주)

* True + True 는 1+1과 같아서 2가 되고, False * 10 은 0 * 10 과 같아서 0이 됨!

- Truthy / Falst

: 파이썬은 조건문에서 특정 값들을 논리적으로 True나 False로 간주하는 개념을 가지고 있음

: 명시적으로 불린 타입이 아니더라도!

* Falsy: False, 0, 0.0, ""(빈 문자열), [](빈 리스트), {}(빈 딕셔너리), ()(빈 튜플), None

* Truthy: Falsy 값을 제외한 대부분의 값(예: 1, "hello", [1], {"a":1})

* 이 두 개념을 잘 이용하면 if 조건문을 더 간결하고 파이썬스럽게 작성 가능. 

예를 들어 if my_list: 라고 쓰면 my_list가 비어있지 않을 때만 조건문 안의 코드가 실행됨!

 

 

데이터 타입 간 변환 및 연산자

형변환(Type Conversion)

- 필요성: 서로 다른 타입의 데이터 간 연산이나 처리를 위해 필요

- 타입 검사

: type(값) is 타입: 특정 값의 타입이 정확히 일치하는지 확인(정확도 높음)

* 예: str(), int(), loat(), bool() ...

: isinstance(값, 타입): 특정 값이 해당 타입이거나 해당 타입을 상속받은 타입인지 확인 (더 유연)

 

산술 연산자

- a + b : 덧셈

- a - b : 뺄셈

- a * b : 곱셈

- a / b : 나눗셈 (결과는 항상 실수)

- a // b : 몫 (정수 나눗셈)

- a % b : 나머지

- a ** b : 거듭제곱

 

문자열 특수 연산

문자열은 숫자와는 다르게 + 와 *연산자를 사용 합니다.

+ 연산자(결합): 이어 붙이기

* 연산자(반복) : 지정된 횟수만큼 반복

 

 

비교 연산자

== : 같다

!= : 같지 않다

< : 작다

> : 크다

<= : 작거나 같다

>= : 크거나 같다

 

문자열 비교

문자열은 유니코드 순서에 따라 비교 (알파벳 순서, 대소문자 구별)

* "apple" < "banana" 는 True.  'a'가 'b'보다 유니코드 값이 작기 때문

* 대소문자 구별. 소문자보다 대문자 유니코드 값이 더 작음! "Apple" < "apple" 은 True

 

 

논리 연산자

- and 그리고 : 두 조건이 모두 True 일 때 True 반환 (둘 중 하나가 False면 전체도 False)

- or 또는 : 두 조건 중 하나라도 True 먄 True 반환

- not 아니다 : 조건의 bool 값을 반대로 뒤집음 (True-> False, False -> True)

 

 

Short-circuit Evaluation 단락 평가

논리 연산자가 불린 값을 결정하기에 충분한 정보가 있을 때,

나머지 표현식을 평가하지 않고 결과를 바로 반환하는 최적화 기법.

"더 이상 계산할 필요가 없으면 멈춰!" 라고 생각하면 쉬움!

 

- False and ... : and 연산에서 첫번째 조건이 False 이면 뒤의 내용은 확인할 필요 없이 전체가 False

- True or ... : or 연산에서 첫번째 조건이 True 이면 뒤의 내용은 확인할 필요 없이 전체가 True

- 값 자체 반환: 단락 평가는 True 또는 False 값 뿐만 아니라 마지막으로 평가된 값 자체를 반환

 

할당 연산자

x = 10: x 에 10을 할당

x += 5: x = x + 5

x -= 3: x = x - 3

x *= 2: x = x * 2

x / = 4: x = x / 4

x / / = 2: x = x / / 2

x %= 2: x = x % 2

x **= 3: x = x **3

- 할당 연산자를 사용하는 이유로는 가독성 향상, 변수명 반복 감수, 성능상 유리의 장점이 있습니다.

 

멤버십 연산자 ( in / not in )

어떤 값이 시퀀스(문자열, 리스트, 튜플 등) 안에 포함되어 있는지 확인

이 연산자들은 데이터를 검색하거나, 특정 조건에 따라 코드를 실행할 때 아주 편리하게 사용됨!

- 값 in 시퀀스 : 값이 시퀀스 안에 있으면 True, 없으면 False

- 값 not in 시퀀스 : 값이 시퀀스 안에 없으면 True, 있으면 False

 

 

조건문

if 조건문은 프로그램이 특정 상황에 따라 다르게 행동하도록 만드는 문법

"만약 ~라면 이렇게 하고, 아니라면 저렇게 해!" 라고 지시하는 것과 같음!

 

- if 문: 가장 기본적인 조건문 (단일 조건)

- if-else 문 : 조건이 True 일 때와 False 일 때 각각 다른 코드 실행 (양자택일)

- if-elif-else 문 : 여러 조건을 순차적으로 확인하고, 해당 조건이 True 일 때 코드 실행 (다중조건)

- Truthy / Falsy 활용