※ 글 최초 작성일자 : 2025. 03. 14
📖 2주 차 스터디노트 작성률: [■■■■■■■■□□] 80%
작성률 100% 예상 일자 : 2025. 03. 16
본 글에서 사용한 자료의 출처 : [코딩테스트 합격자 되기 파이썬 편 책]
아쉽게도 책의 4장 [코딩 테스트 필수 문법]은 인프런에 강의가 없다.
c++ 편은 있지만 파이썬 편 강의는 없어서 책을 보고 정리를 해봤다.
코딩테스트 준비를 하면서 문제를 많이 풀어봤거나 전공자라면 이미 알고 있는 내용이라 생각한다.
책에 있는 내용과 내가 알고 있는 부분을 잘 녹여서 글을 작성해 봤다.
▶ 책 4장 [코딩 테스트 필수 문법] 목차
- 빌트인 데이터 타입 ✔
- 컬렉션 데이터 타입
- 함수
- 코딩테스트 코드 구현 노하우
1. 빌트인 데이터 타입
빌트인 데이터 타입(built-in data type)은 언어 자체에서 제공하는 데이터 타입과 컬렉션 데이터 타입이 있음
기본 데이터 타입 : 정수형(int), 부동소수형(float), 문자열 타입
컬렉션 데이터 타입 : 리스트, 튜플, 셋, 딕셔너리 등
▶ 정수형
정수형은 양과 음의 정수, 0을 포함함
우리가 흔히 하는 사칙 연산 외 많은 연산을 할 수 있음(ex. ** 연산자, //연산자 사용한 연산)
저자님 말씀으로는 연산자는 글보다는 코드를 보며 공부하는 것이 훨씬 직관적이고 이해하기 쉽다고 한다.
- 정수형 변수 선언 코드
a = 13
b = 4
- 정수형 산술 연산 코드
# a = 13, b = 3
print(a + b) # 더하기 17
print(a - b) # 빼기 9
print(a * b) # 곱하기 52
print(a / b) # 나누기(소수점 포함) 3.25
print(a // b) # 나누기(소수점 제외) 3
print(a % b) # 모듈러 연산(나머지) 1
print(-a) # 부호를 바꿈 -13
print(abs(-a)) # 절대값 13
print(a**b) # a의 b승 28561
- 정수형 비교 연산 코드
# a = 13, b = 3
print(a == b) # 같은 값인지 비교 False
print(a !=b) # 같지 않은 값인지 비교 True
print(a > b) # 값이 더 큰지 비교 True
print(a >= b) # 왼쪽 값이 더 크거나 같은지 비교 True
- 정수형 비트 연산
# a = 13, b = 3
print(a & b) # AND 4
print(a | b) # OR 13
print(a ^ b) # XOR 9
print(~a) # NOT -14
print(a << 2) # 왼쪽 시프트 (a에 2^2를 곱한 것과 동일) 52
print(a >> 1) # 오른쪽 시프트 (a를 2^1로 나눈 것과 동일) 6
★코드 설명 (이해하기 쉽게)★
보다시피 처음에 a = 13, b = 4라고 선언했다.
비트 연산을 하기 위해서 13, 4와 같은 숫자를 2진수(비트)로 표현해줘야 한다.
a = 13 → 1101(2진수)
b = 4 → 0100(2진수)
이제 바로 위의 코드를 보자
AND 연산을 한 결과가 4라고 하는데, 어떻게 계산이 된 걸까?
AND 연산(&)은 두 숫자의 각 비트를 비교해서 둘 다 1일 때만 1, 아니라면 0이 된다.
예를 들면
1 AND 1 → 1
1 AND 0 → 0이다.
그러면 a & b를 계산하면 어떻게 될까?
1101 (a)
0100 (b)
0100이므로 결과는 4가 된다.
다음으로 OR 연산(|)을 보자
계산하기 위해서는 먼저 OR 연산이 무엇인지 알아야 한다.
OR 연산은 두 숫자의 각 비트를 비교해서 하나라도 1이면 1, 아니라면 0이 된다.
예를 들면
1 OR 1 → 1
1 OR 0 → 1
0 OR 0 → 0이다.
그러면 계산을 해보자
1101 (a)
0100 (b)
1101이므로 결과는 13이 된다.
다음으로 XOR 연산(^)을 보자
XOR 연산은 두 숫자의 각 비트를 비교해서 비트 값이 다르면 1, 같으면 0이 된다.
예를 들면
1 XOR 1 → 0
1 XOR 0 → 1
0 XOR 0 → 0이다.
그럼 이제 계산을 해보자
1101 (a)
0100 (b)
1001이므로 결과는 9가 된다.
이번에는 NOT 연산(~)을 보자
NOT 연산은 모든 비트를 반전시킨다.
0 → 1, 1 → 0이 된다.
1101 (a)를 NOT 연산한다면
비트반전이 되어서 0010이 되니까...
그러면 10진수로 2가 되어야 하는 거 아닌가요? 할 수 있다.
사실 그렇게 계산되는 게 아니다. (아래 추가 설명을 참고)
하지만 파이썬에서는 2의 보수 표현을 사용해서 ~a = -a -1이 된다.
~13 = -(13 + 1) = -14가 결과가 된다.
※ 추가 설명(tmi)
위에서 NOT 연산으로 print(~a)를 했더니 -14가 출력이 되었다. (a = 13)
왜 그렇게 되는 걸까?
이걸 이해하려면 2의 보수(음수 표현 방식)를 먼저 알아야 한다.
컴퓨터는 양수와 음수를 표현하는 통일된 방법이 필요한데
이때 2의 보수 방식을 사용하면 덧셈과 뺄셈을 똑같이 처리할 수 있다.
- 2의 보수 특징
- 숫자의 첫 번째 비트(가장 왼쪽 비트)를 부호 비트로 사용
- 0이면 양수
- 1이면 음수
- 양수를 음수로 바꿀 때는 비트 반전 후 1을 더하면 된다. (위에서 했던 것처럼)
- 숫자의 첫 번째 비트(가장 왼쪽 비트)를 부호 비트로 사용
- 2의 보수 구하는 법 (양수를 음수로 변환하는 방법)
- 양수의 이진수 표현을 구함
- 비트를 반전(0 → 1, 1 → 0)
- 1을 더한다
위에서 13의 NOT 연산을 했는데 다시 한번 그 과정을 보면
13을 2진수로 변환하면 1101이 된다.
(중요한 부분)
컴퓨터는 숫자를 저장할 때 고정된 비트 크기를 사용한다.
8비트, 16비트, 32비트 등
이 말은 즉슨 비트 연산을 수행할 때 특정 크기의 비트 안에서 연산해야 한다는 말이다.
13(1101)만 가지고 비트 반전을 하면 4비트 숫자로 처리하는 것처럼 보일 수 있으나
대부분의 컴퓨터는 8비트 이상을 사용하므로 8비트로 확장해서 계산해야 하는 게 옳다.
그러면 2진수 1101을 8비트로 표현해서 비트반전을 수행해 보자
10진수 13 → 2진수 1101 → 8비트 표현 00001101
비트 반전을 수행하면
11110010이 된다.
이때 숫자의 첫 번째 비트가 1이므로 음수인 것을 확인
그러면 2의 보수 방식으로 해석해야 함
어떻게? 비트 반전 후 1 더하기
11110010 → 00001101 + 1 → 00001110이 된다.
10진수로 변환하면 14인데 음수 변환까지 해주면 -14가 된다.
거의 다 왔다. 왼쪽 시프트(<<)가 뭔지 알아보자.
왼쪽 시프트는 비트를 왼쪽으로 n칸 밀어서 2^n을 곱하는 친구다.
예를 들면
a << 1 → a * 2
a << 2 → a * 4
a << 3 → a * 8이다.
그러면 위 코드처럼 a << 2를 계산해 보자
1101 << 2 → 110100이므로 결과는 52이다.
앞서 말한 것처럼 a = 13이므로 a*4 = 52라고 계산해도 되겠다.
왼쪽 시프트가 있으면 오른쪽 시프트(>>)도 있다.
오른쪽 시프트는 비트를 오른쪽으로 n칸 밀어서 2^n으로 나누는 친구다.
예를 들면
a >> 1 → a // 2
a >> 2 → a // 4
a >> 3 → a // 8이다.
그러면 위 코드처럼 a >> 1을 계산해 보자
1101 >> 1 → 0110이므로 결과는 6이다.
앞서 말한 것처럼 a = 13이므로 13 // 2 = 6이라고 계산해도 되겠다.
- 정수형 논리 연산
# a = 13, b = 3
print(a and b) # 논리 연산 AND 4
print(a or b) # 논리 연산 OR 13
print(not a) # 논리 연산 NOT False
★코드 설명 (간단하게)★
- 논리 AND
- A and B는 A가 False면 A 반환, 그렇지 않으면 B 반환
- 파이썬에서 0만 False, 나머지 숫자는 True
- a = 13 (True)
- b = 3 (True)
- a and b : a가 True 이므로 b를 반환
- 출력 결과 : 3
- 논리 OR
- A or B는 A가 True면 A 반환, 그렇지 않으면 B 반환
- a = 13 (True)
- b = 3 (True)
- a or b : a가 True 이므로 a를 반환
- 출력 결과 : 13
- 논리 NOT
- not A는 A가 Ture이면 False 반환, A가 False 이면 True 반환
- a = 13 (True)
- not a : False 반환
- 출력 결과 : False
▶ 부동소수형
부동소수형은 소수를 저장할 때 사용함
- 부동소수형 사칙 연산
print(2.5 + 3.7) # 더하기 6.2
print(7.9 - 4.2) # 빼기 3.7
print(1.5 * 4.8) # 곱하기 7.199999999999999
print(10.0 / 3.2) # 나누기 3.125
★코드 설명★
float 연산은 실수를 다룰 때 사용되는 연산
- 코드에서 1.5 * 4.8을 했는데 왜 7.2가 아니라 7.199999999999999가 될까?
- 컴퓨터는 실수를 2진수로 변환해서 저장함
- 10진수의 일부 소수는 2진수로 정확하게 표현할 수 없음
- ex 1) 10진수 0.1을 2진수로 변환
- 0.1 (10진수) → 0.0001100110011001100110011001100...(2진수, 무한 반복된다)
- 0.1은 2진수에서 무한히 반복되므로, 컴퓨터는 근사값으로 저장함
- 이 과정에서 아주 작은 오차가 발생할 수 있음
- ex 2) 4.8을 2진수로 변환
- 4.8 (10진수) → 100.1100110011001100110011...(2진수, 무한 반복된다)
- 0.8이 무한 반복된다
- 우리 컴퓨터는 4.8을 완벽하게 저장할 수 없고, 근사값을 저장함
- 1.5 * 4.8을 계산해 보자
- 우리가 직접 산수 해서 값을 구하면 7.2라는 값이 나온다
- 하지만 컴퓨터에서 계산한다면 위에서 말했다시피 근사값을 사용함
- 실제로 계산되는 값은 (1.5000000000000000) * (4.7999999999999998)이므로
- 결과값은 7.199999999999999이다.
- 정확하게 계산하고 싶은데 방법이 없을까?
- round() 함수를 사용하거나 decimal 모듈 사용하면 된다.
print(round(1.5 * 4.8, 2)) # 7.2
from decimal import Decimal
a = Decimal("1.5")
b = Decimal("4.8")
print(a * b) # 7.2
- 부동소수형 정수형 나누기, 모듈러, 제곱 연산
print(10.0 // 3.2) # 정수형 나누기 3.0
print(10.0 % 3.2) # 모듈러 0.39999999999999947
print(2.0 ** 3.2) # 제곱 연산 9.18958683997628
★코드 설명★
- 정수형 나누기
- // 연산자는 몫만 반환하고 소수점 아래는 버림
- 부동소수점 오차가 없는 정확한 값 3.0이 결과로 나옴
- 모듈러 (나머지 연산)
- a % b : a를 b로 나눈 후 나머지를 반환
- 부동소수점 오차 발생 가능함
- 이론적으로는 10.0 ÷ 3.2 = 3.125 (몫)
몫의 정수 부분: 3
나머지 = 10.0 - (3.2 × 3) = 10.0 - 9.6 = 0.4이 되어야 함 - 그러면 왜 0.39999999999999947가 나올까?
- 이전 코드 설명에서 말했다시피 3.2 자체가 이진수로 정확하게 표현되지 않음!
- 3.2의 내부 저장 값은 3.1999999999999997
- 따라서 (10.0 - (3.2 × 3)) 계산 시 부동소수점 오차가 발생함
- 계산 결과 : 0.39999999999999947
- 제곱 연산
- a ** b 연산자는 a의 b 제곱을 계산
- 이 또한 부동소수점 오차로 인해 근사한 값이 출력되었음
- 2^3.2 = 2^(3 + 0.2)
= (2^3) * (2^0.2)
= 8 * 1.148698354997035
≈ 9.18958683997628 - 이전 코드 설명에서 말한 부동소수점 오차 해결법을 적용하면 정확한 값을 출력할 수 있음
▶ 앱실론을 포함한 연산에 주의
주의해야 하는 이유 : 파이썬은 부동소수형 데이터를 이진법으로 표현하기 때문
표현 과정에서 오차가 발생하는데 이를 엡실론(epsilon)이라고 한다.
코딩 테스트에서 부동소수형 데이터를 다룰 일이 생겼을 때 이 엡실론을 항상 생각해야 함!!
우리가 부동소수형을 사용하여 코드를 작성하면
엡실론이라는 요소 때문에 일부 테스트 케이스가 통과하지 못할 수도 있으므로 유의해야 함
import sys
# 부동소수점 오차 확인(엡실론 출력)
print(sys.float_info.epsilon) # 2.220446049250313e-16
# 부동소수점 수의 오차 검사
a = 0.1 + 0.1 + 0.1
b = 0.3
print(a - b) # 5.551115123125783e-17 (0이 아닌 아주 작은 값임)
# 오차 범위 내에서 비교하는 방법
if abs(a - b) < sys.float_info.epsilon:
print("a와 b는 같은 값입니다.") # 이 코드가 출력됨
else:
print("a와 b는 다른 값입니다.")
부동소수형 데이터를 활용하는 문제는 오차 허용 범위를 언급하는 경우가 많음
문제를 분석할 때 꼭 이 부분을 체크해야 함 (많은 사람들이 실수하기 때문)
2. 컬렉션 데이터 타입
컬렉션은 여러 값을 담는 데이터 타입을 말함
대표적으로 리스트(list), 튜플(tuple), 딕셔너리(dictionary), 셋(set), 문자열(string)등이 있다.
이 컬렉션들은 데이터의 수정 가능 여부에 따라 2가지로 구분함
변경할 수 있는 객체(mutable object)와 변경할 수 없는 객체(immutable object)
뮤터블 객체와 이뮤터블 객체는 값의 수정 유무의 특징이 있으므로 동작하는 방식이 다름
▶ 뮤터블 객체
뮤터블 객체(mutable object)는 객체 생성 후 객체를 수정할 수 있다.
대표적인 뮤터블 객체 : 리스트, 딕셔너리, 셋
my_list = [1, 2, 3, 4, 5] # 리스트 객체 생성, [1, 2, 3, 4, 5]
my_list[4] = 6 # 리스트 원소 변경
print(my_list) # [1, 2, 3, 4, 6]
★코드 설명★
my_list가 참조하고 있는 [1, 2, 3, 4, 5]에서 5번째 위치에 있는 값을 6으로 수정하였음
▶ 이뮤터블 객체
이뮤터블 객체(immutable object)는 객체 생성 후 객체를 수정할 수 없다.
대표적인 이뮤터블 객체 : 정수, 부동소수점, 문자열, 튜플
(뮤터블, 이뮤터블 설명을 위해 정수를 빌려와 예시로 들었음. 정수가 컬렉션 데이터 타입에 포함되는 것은 아님)
a = 4
b = a # b도 a와 같은 객체(4)를 참조
b += 2 # b에 6을 할당하면 새로운 객체를 생성하고 b가 참조하도록 변경
print(a, b) # 4 6
★코드 설명★
- a = 4 일 때
- a가 4라는 객체를 참조함
- b = a
- a가 참조한 4라는 이뮤터블 객체를 b도 똑같이 참조함
- b += 2
- b는 6이라는 객체를 참조함
- 4는 이뮤터블 객체이므로 수정할 수 없음
- 따라서 객체 6을 새로 생성하고 그 객체를 참조함
▶ 리스트
리스트는 뮤터블 객체(mutable object)이다.
[ ]로 원소를 감싸는 형태로 사용한다.
리스트는 '시퀀스(순서)가 있는 자료형이다'라고 말한다.
이런 특징으로 리스트는 인덱싱, 슬라이싱을 할 수 있다.
# 리스트 선언
my_list = [1, 2, 3, 4, 5]
my_list2 = [1, 3, 5] + [7, 9] # 리스트 연결
my_list3 = list(my_list) # 리스트 복사
print(my_list) # [1, 2, 3, 4, 5]
print(my_list2) # [1, 3, 5, 7, 9]
print(my_list3) # [1, 2, 3, 4, 5]
★코드 설명★
+ 연산자를 사용해서 리스트를 연결해서 새로운 리스트를 생성할 수 있다.
list( )를 사용하여 기존 리스트를 복사할 수 있다.
(주의사항)
my_list3 = my_list로 하면 같은 객체를 참조하므로 한쪽을 변경하면 다른 리스트도 변경된다.
따라서 리스트 복사를 할 때는 list() 또는 copy() 사용을 권장한다.
▶ 리스트 인덱싱
인덱싱이란?
인덱스를 활용해서 특정 위치의 원소에 접근하는 것을 말한다.
ex) 아래 코드에서 3번째 인덱스에 접근하는 my_list[2] 코드를 작성했는데
이를 '인덱싱으로 원소에 접근한다'라고 표현한다.
아래 코드를 통해 이해하는 시간을 가져보자
my_list = [1, 2, 4]
# 값 추가
my_list.append(6)
print(my_list) # [1, 2, 4, 6]
# 인덱싱으로 값 삭제
del my_list[2]
print(my_list) # [1, 2, 6]
★코드 설명★
append() 는 리스트의 맨 끝에 값을 추가하는 함수이다.
새로운 리스트를 생성하지 않고 기존 리스트를 직접 수정해서 사용할 수 있다.
del 키워드는 특정 인덱스의 원소를 삭제하는 기능을 한다.
del my_list[2]는 인덱스 2의 값(4)을 삭제하고 리스트를 재정렬한다.
▶ 리스트 슬라이싱
슬라이싱은 시퀀스 자료형의 범위를 지정해서 값들을 복사하여 가져오는 방식
슬라이싱은 파이썬 코드로 list_name[a:b]와 같이 작성
위와 같이 작성한 코드는 인덱스 a 이상부터 b 미만에 해당하는 원소를 새 리스트에 담아 반환
음수 인덱스를 활용한 슬라이싱도 가능하다.
my_list = [1, 2, 3, 4, 5]
print(my_list[0:2]) # [1, 2]
print(my_list[1:]) # [2, 3, 4, 5]
print(my_list[3:4]) # [4]
print(my_list[-4:-2]) # [2, 3]
★코드 설명★
- my_list[0:2]
- 0:2는 인덱스 0 이상, 2 미만의 값만 선택
- 0과 1번 인덱스만 선택
- 결과 : [1, 2]
- my_list[1:]
- 1: 은 인덱스 1부터 끝까지 가져온다는 의미
- 1번 인덱스의 값은 2
- 결과 : [2, 3, 4, 5]
- my_list[3:4]
- 3:4는 인덱스 3 이상, 4 미만의 값만 선택
- 3번 인덱스의 값 하나만 선택 : 4
- 결과 : [4]
- my_list[-4:-2]
- 음수 인덱스를 사용하면 리스트의 뒤에서부터 요소를 선택할 수 있다
- 양수 인덱스의 경우 my_list[0] → 1이지만
- 음수 인덱스의 경우 my_list[-1] → 5이다
- my_list[-2]의 경우에는 → 4가 되겠다 (뒤에서 두 번째 요소)
- 그러면 my_list[-4:-2]는 음수 인덱스 -4부터 -2 미만까지 선택한다는 의미
- 결과 : [2, 3]
▶ 딕셔너리
파이썬의 딕셔너리(dictionary)는 뮤터블 객체(mutable object)이다.
키(key)와 값(value) 쌍을 저장하는 해시 테이블로 구현되어 있다. 이름 그대로 키를 사용하여 값을 검색하는 자료형이다.
▶ 딕셔너리 초기화
딕셔너리 하나 선언
my_dict = { }
★코드 설명★
{}를 사용하면 빈 딕셔너리 생성
▶ 딕셔너리 삽입과 출력
선언한 딕셔너리에 값을 삽입하고 딕셔너리 전체를 출력
# 딕셔너리 값 삽입
my_dict["apple"] = 1
my_dict["banana"] = 2
my_dict["orange"] = 3
# 딕셔너리 값 출력
print(my_dict) # {'apple': 1, 'banana': 2, 'orange': 3}
혹은 이렇게 코드를 작성할 수도 있다.
# 키와 값 쌍을 포함한 딕셔너리 생성
my_dict = {
"apple": 1,
"banana": 2,
"orange": 3
}
print(my_dict) # {'apple': 1, 'banana': 2, 'orange': 3}
★코드 설명★
- {키: 값, 키 : 값} 형태로 초기화 가능
- print(my_dict)을 사용하면 키-값 쌍이 포함된 딕셔너리 출력
- 딕셔너리는 순서가 없음. 해시 테이블 구조
▶ 딕셔너리 검색
my_dict가 참조하는 딕셔너리의 키들을 보며 "apple" 문자열이 일치하는지 확인하고
일치하는 키를 찾으면 키-값을 출력
key = "apple"
# 키 존재여부 확인
if key in my_dict:
value = my_dict[key]
print(f"{key}: {value}") # apple: 1
else:
print(f"{key} 키가 딕셔너리에 존재하지 않습니다.")
★코드 설명★
- if key in my_dict : 해당 키가 딕셔너리에 존재하는지 확인
- my_dict[key] : 해당 키의 값을 가져옴
- print(f"{key}: {value}") : 키와 값을 출력 (ex: apple: 1)
- else: 부분으로 키가 없을 때 없다고 알려줌
▶ 딕셔너리 수정
키 "banana"를 검색하여 해당 키의 값을 4로 바꾸자
앞서 말한 것처럼 딕셔너리 내부는 해시 테이블로 구성되어 있으므로 해시 테이블에서 키를 찾거나 하지 않아도 된다.
my_dict["banana"] = 4
print(my_dict) # {'apple': 1, 'banana': 4, 'orange': 3}
★코드 설명★
- 기존 "banana" 키의 값은 2
- my_dict["banana"] = 4 코드를 통해 "banana"의 키 값을 4로 변경하였음
- 딕셔너리는 해시 테이블 구조이므로 키를 통해 값을 빠르게 변경할 수 있다 (O(1) 연산속도)
▶ 딕셔너리 삭제
키 "orange"를 찾아 딕셔너리에서 삭제
# 특정 키 삭제
del my_dict["orange"]
print(my_dict) # {'apple': 1, 'banana': 4}
★코드 설명★
- del my_dict["orange"] : 해당 키 "orange"를 삭제
- 존재하지 않는 키를 삭제하려 하면 KeyError가 발생함
딕셔너리에 키가 없는 경우를 처리하는 예외 처리(에러 방지)
# 딕셔너리 생성
my_dict = {"apple": 1, "banana": 2, "cherry": 3}
# my_dict에 존재하지 않는 key로 설정
key = "kiwi"
# 키가 딕셔너리에 있는지 확인
if key in my_dict:
# 키가 딕셔너리에 있으면 해당 값 출력
print(f"값: {my_dict[key]}")
else:
# 키가 딕셔너리에 없으면 에러 메시지 출력
print(f"'{key}' 키가 딕셔너리에 없습니다.")
★코드 설명★
- 주석으로 설명을 했으므로 참고
- 이렇게 코드를 작성하면 keyError 발생을 방지할 수 있다
▶ 딕셔너리 추가
(책에는 없는 내용)
만약에 딕셔너리에 값을 추가하고싶으면 어떻게 해야할까?
my_dict = {"apple": 1, "banana": 2, "cherry": 3}
my_dict["grape"] = 4
print(my_dict)`# {'apple': 1, 'banana': 2, 'cherry': 3, 'grape': 4}
★코드 설명★
- my_dict["grape"] = 4 : 새로운 키 "grape"에 값 4를 추가함
- 존재하지 않는 키에 값을 할당하면 새로운 키-값 쌍이 추가된다
▶ 튜플
튜플은 이뮤터블 객체(immutable object)이다.
위에서 다룬 리스트, 딕셔너리와 달리 한 번 생성하면 삽입하거나 삭제할 수 없는게 특징이다.
▶ 튜플 초기화
튜플은 아래와 같이 ( )를 사용하여 초기화한다. (생성한다)
my_tuple = (1, 2, 3)
print(my_tuple) # (1, 2, 3)
★코드 설명★
- ( ) 소괄호를 사용하여 튜플 초기화(생성)
- [ ] 리스트와 달리 값을 변경할 수 없음
▶ 튜플 인덱싱, 슬라이싱
위에서 말했듯 튜플은 삽입, 삭제는 되지 않지만 인덱싱, 슬라이싱은 할 수 있다.
문법 자체는 리스트와 같다.
my_tuple = (1, 2, 3)
# 튜플 인덱싱
print(my_tuple[0]) # 1
print(my_tuple[1]) # 2
print(my_tuple[2]) # 3
# 튜플 슬라이싱
print(my_tuple[1:]) # (2, 3)
print(my_tuple[:2]) # (1, 2)
print(my_tuple[1:2]) # (2,)
★코드 설명★
- 튜플 인덱싱 설명
- 인덱스 0, 1, 2 를 사용해 요소를 가져올 수 있음
- 튜플의 첫 번째 요소는 my_tuple[0], 두번째는 my_tuple[1]
- 튜플 요소를 조회는 가능, 값 변경은 불가
- 튜플 슬라이싱 설명
- 문법 : my_tuple[start:end]
- my_tuple[1:] : 인덱스 1 부터 끝까지 → (2, 3)
- my_tuple[:2] : 처음부터 인덱스 2 미만까지 → (1, 2)
- my_tuple[1:2] : 인덱스 1 이상 2 미만 → (2, )
- ※ 튜플에서 단일 요소일 경우 , 가 붙음!
▶ 튜플 vs 리스트
리스트에 모든 기능이 있는데 튜플을 사용하는 이유가 무엇일까?
앞서 말한것 처럼 리스트(list)는 값을 변경할 수 있는 뮤터블(mutable) 자료형이고
튜플(tuple)은 값을 변경할 수 없는 이뮤터블(immutable) 자료형이다.
이 말은 즉, 튜플을 사용하면 데이터가 변경되지 않는다는 보장이 있으므로
코테에서 실수를 방지할 수 있다.
심지어 메모리 사용이 적고 실행 속도가 리스트보다 빠르다.
고정된 데이터 저장(ex. 좌표값 등)에 적합해 보인다.
▶ 문자열
문자열은 문자들을 집합 형태로 구성한 이뮤터블(immutable) 객체이다.
▶ 문자열 초기화
문자열은 큰따옴표나 작은따옴표로 감싸 사용한다.
# 문자열 생성
string = "Hello, World!" # 큰따옴표 사용
string2 = 'Hello, World!' # 작은따옴표 사용
★코드 설명★
- 큰따옴표(" ") 또는 작은따옴표(' ')를 사용하여 문자열 생성 가능
- 두 방법 모두 동일하게 작동함
▶ 문자열 추가, 삭제
문자열은 이뮤터블 객체이므로 기존 객체를 수정하는 것이 아닌 새로운 객체를 반환한다.
# 문자열 추가(연결)
string = "He" # 기존 문자열
string += "llo" # "He" + "llo" → 새로운 문자열 "Hello" 생성함
print(string) # Hello
★코드 설명★
- string = "He" : 문자열 "He"를 생성하여 변수에 저장
- string += "llo" : 기존 문자열 "He"에 "llo"를 추가하여 새로운 문자열 "Hello"를 생성함
▶ 문자열 수정
replace( ) 메서드를 사용하여 문자열을 수정한다.
replace( ) 메서드는 첫 번째 인수에 찾을 문자열을, 두 번째 인수에 변경할 문자열을 넣어 사용한다.
string = "Hello"
string = string.replace("l", "") # "l"을 모두 삭제
print(string) # Heo
★코드 설명★
- string = "Hello" : 문자열 "Hello"를 생성
- string.replace("l", "") : 문자 "l"을 모두 제거한 새로운 문자열 "Heo"를 반환, 기존 변수에 새로운 문자열을 다시 할당
3. 함수
함수는 프로그래밍에 중요한 요소
보편적으로 알고있는 내용이므로 코딩 테스트를 위해 알아야 할 내용만 빠르게 알고 넘어가자
▶ 함수 정의
파이썬의 함수는 def라는 예약어를 사용하여 정의한다.
def function_name(param1, param2, param3, ..., paramN):
# 함수 실행 코드
...
return result # 반환값
★코드 설명★
- def : 함수를 정의하는 키워드
- function_name : 함수 이름(원하는 이름으로 작성)
- param1, param2, ... , paramN : 매개변수(함수에 입력되는 값)
- return result : 함수 실행 결과를 반환함 (생략할 수 있음)
▶ 함수 호출
위에서 함수를 정의하는 법을 알았다.
함수를 정의했으면 함수를 호출할 수 있는데 매개변수가 있는 경우 func(a, b)와 같이 인수를 함께 전달한다.
def add(num1, num2):
result = num1 + num2
return result
# 함수 호출
ret = add(5, 10)
print(ret) # 15
★코드 설명★
- def add(num1, num2) : 두 개의 매개변수를 받는 add() 함수 정의
- result = num1 + num2 : 두 숫자를 더한 결과를 result 변수에 저장함
- return result : result 값을 반환하여 함수 호출 부분에서 사용할 수 있게 함
- ret = add(5, 10) : 함수 호출 후 반환값을 ret 변수에 저장함
▶ 람다식
파이썬은 람다식(lambda expression)을 사용할 수 있다.
'그룹 스터디(책 기반으로) > 코테 합격자되기 파이썬' 카테고리의 다른 글
코테 스터디 1주차 [알고리즘의 효율 분석-시간 복잡도] (2) | 2025.03.15 |
---|---|
코테 스터디 0주차 [효율적으로 코딩 테스트 공부하기] (3) | 2025.03.04 |