# [Python] 파이썬 기초 자료형

## **자료형**

---

- 파이썬에는 정수형, 실수형, 복소수형, 문자열, 리스트 등 다양한 자료형이 존재

- 자료형에 따라 지원하는 연산자 및 메소드들이 다르다

- 사용자의 필요성에 따라 적절한 자료형을 선택하여 사용

| **자료형** | **형식** | **설명** |
| --- | --- | --- |
| **int 형** | n = 100 n += 200 | 음의 정수, 0, 양의 정수 값을 가지며  사칙 연산자를 비롯한 연산자를 사용할 수 있다 |
| **float 형** | f = 12.3 f = f - 30.12 | 소숫점 아래 숫자를 가질 수 있으며, 정밀한 숫자 표현이 가능 정수형에서 사용하는 연산자를 많이 사용할 수 있다 |
| **complex 형** | a = 3 + 2.0J | 실수부와 허수부를 가지는 복소수를 표현할 수 있는 자료형 |
| **str형** | s = “hello” s = s * 3 s.upper() | 문자열을 저장 문자열 반복 연산자를 지원 upper(), lower(), split() 등 메소드 지원 |

**변수**

```javascript
변수_이름 = 변수에_저장할_값
```

- a, b, c와 같이 값들을 저장하는 것을 변수라고 한다

- 변수를 만들 때는 `=`  기호를 사용

- C나 Java는 변수를 만들 떄 자료형을 직접 지정하지만 
- 파이썬은 변수에 저장된 값을 스스로 판단하여 자료형의 타입을 지정

### 동적 타이핑 vs 정적 타이핑

**동적 타이핑**

```javascript
 a = [1, 2, 3, 4] # 리스트 객체 생성, 변수 a가 이 객체를 참조
 a = 'Hello'      # 변수 a가 문자열 객체를 참조
```

- 파이썬 변수의 형은 실행 시에 결정

- 변수는 객체에 대해서 바운드, 객체는 임의의 형이 될 수 있다

    - **바인딩**: 변수에 변수와 관련된 속성을 연관되는 것을 말함

- 한 자료형의 객체에 변수 이름 a가 할당되면, 나중이 이 이름 a는 다른 자료형 객체 참조에 사용될 수 있다

**정적 타이핑**

```javascript
int n = 100;
```

- C, C++, Java와 같은 프로그래밍 언어에서는 선언을 통해 참조하는 형이 고정

- 정적 타이핑 언어는 변수의 자료형이 컴파일할 떄 결정

- 변수는 사용기간 동안 한 가지 자료형만 참조 가능 
- → 변수의 형을 실행할 때 변경할 수 없다

## 다양한 자료형

---

| **항목** | **형식** | **설명** |
| --- | --- | --- |
| **정수 int** | n = 123  n = -178  n = 0 | 음의 정수, 0, 양의 정수 값을 가지며  사칙 연산자를 비롯한 연산자를 사용할 수 있다 |
| **실수 float** | f = 1.2  f = 4.24E10  f = 4.24e-10 | 소숫점 아래 숫자를 가질 수 있으며, 정밀한 숫자 표현이 가능  정수형에서 사용하는 연산자를 많이 사용할 수 있다 |
| **8진수** | o = 0o34 | 숫자를 8진수로 나타낼 수 있다 |
| **16진수** | x = 0xABC | 숫자를 16진수로 나타낼 수 있다 |
| **복소수 complex** | c = 3+2.0i | 실수부와 허수부를 가지는 복소수를 표현할 수 있는 자료형 |

### 연산자

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/225916_QH0UwOJOY4hMwDwXUI?q=80&s=1280x180&t=outside&f=webp)

**산술 연산자**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `+` | 덧셈 | `3 + 2` -> `5` |
| `-` | 뺄셈 | `3 - 2` -> `1` |
| `*` | 곱셈 | `3 * 2` -> `6` |
| `/` | 나눗셈 (결과는 실수) | `3 / 2` -> `1.5` |
| `//` | 몫 (정수 나눗셈) | `3 // 2` -> `1` |
| `%` | 나머지 | `3 % 2` -> `1` |
| `**` | 거듭제곱 | `3 ** 2` -> `9` |

**비교연산자**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `==` | 같다 | `3 == 3` -> `True` |
| `!=` | 같지 않다 | `3 != 2` -> `True` |
| `>` | 크다 | `3 > 2` -> `True` |
| `<` | 작다 | `3 < 2` -> `False` |
| `>=` | 크거나 같다 | `3 >= 2` -> `True` |
| `<=` | 작거나 같다 | `3 <= 2` -> `False` |

**논리 연산자**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `and` | 논리적 AND (둘 다 참일 때 참) | `True and False` -> `False` |
| `or` | 논리적 OR (둘 중 하나만 참이면 참) | `True or False` -> `True` |
| `not` | 논리적 NOT (참이면 거짓, 거짓이면 참) | `not True` -> `False` |

**대입연산자**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `=` | 대입 | `x = 5` |
| `+=` | 더한 후 대입 | `x += 3` (x = x + 3) |
| `-=` | 뺀 후 대입 | `x -= 3` (x = x - 3) |
| `*=` | 곱한 후 대입 | `x *= 3` (x = x * 3) |
| `/=` | 나눈 후 대입 | `x /= 3` (x = x / 3) |
| `//=` | 몫을 구한 후 대입 | `x //= 3` (x = x // 3) |
| `%=` | 나머지를 구한 후 대입 | `x %= 3` (x = x % 3) |
| `**=` | 거듭제곱 후 대입 | `x **= 3` (x = x ** 3) |

**멤버십 연산자**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `in` | 포함되어 있는지 확인 | `'a' in 'apple'` -> `True` |
| `not in` | 포함되지 않은지 확인 | `'b' not in 'apple'` -> `True` |

**식별 연산자**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `is` | 동일한 객체인지 확인 | `x is y` |
| `is not` | 동일하지 않은 객체인지 확인 | `x is not y` |

**비트 연산자**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `&` | 비트 AND | `5 & 3` -> `1` |
| ` | ` | 비트 OR |
| `^` | 비트 XOR | `5 ^ 3` -> `6` |
| `~` | 비트 NOT | `~5` -> `-6` |
| `<<` | 비트 왼쪽 시프트 | `5 << 1` -> `10` |
| `>>` | 비트 오른쪽 시프트 | `5 >> 1` -> `2` |

**조건부 표현식**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `x if condition else y` | 조건이 참이면 x, 거짓이면 y 반환 | `3 if 5 > 2 else 4` -> `3` |

**함수 호출 연산자**

| **연산자** | **설명** | **예시** |
| --- | --- | --- |
| `()` | 함수 호출 | `print("Hello, world!")` |

**왈러스 연산자**

- Python 3.8에서 도입

- 할당 표현식을 사용하게 해주는 연산자

- “이름을 표현식의 결과에 연결”하거나 “값을 이름에 할당하면서 그 값을 평가”

- 표현식을 계산하면서 동시에 그 결과를 변수에 할당할 수 있음

```javascript
# 기본적인 왈러스 연산자의 사용
x = (n := 10) * 2 # 10을 n에 할당, 그 값을 반환
print(x) # 출력: 20
print(n) # 출력: 10
```

```javascript
# 왈라스 연산자가 없을 때의 코드
import random

while True:
    x = random.randint(0, 10)
    if x == 7:
        break
    print(x)

# 왈라스 연산자를 사용한 코드
import random

while(x := random.randint(0, 10)) != 7:
    print(x)
```

```javascript
def sigma(n):
    count = 0
    result = 0
    while(count := count+ 1) < n + 1:
        result += count
    return result

if(sum := sigma(100)) ** 5050:
    print('5050이 출력되었습니다.')
else:
    print('1부터 정수형태로 입력이 가능합니다.')
print(sum * 1000)
```

**왈러스 연산자 주의사항**

- 할당 연산자와 비슷하지만, 활용 범위와 용도가 다르므로 사용에 주의해야한다

- 코드의 가독성을 위해 복잡한 표현식 내에서 알러스 연산자의 남용을 피해야한다

- 복잡한 한 줄 코드 보다는 여러 줄에 걸친 명확한 코드가 유지보수와 이해에 더 좋을 수 있다

- 연산자를 통해 코드의 효율성과 가독성을 높일 수 있다. 그러나 남용하면 코드의 가독성을 오히려 떨어뜨릴 수 있으므로 적절한 균형이 중

### C vs Python

```javascript
a = 100
b = a
print(id(a)) # 객체 a의 id 반환
print(id(b)) # 객체 b의 id는 a와 같다 (같은 객체를 참조)
```

- 파이썬에서 모든 객체는 고유한 id를 가진다

- `=` 연산자를 사용하면 객체에 대한 **참조를 만들거나 변경**시킨다

- 파이썬은 객체 중심 프로그래밍 언어 → 객체와 객체를 참조하는 변수, 참조 변경이 중요

- 객체를 여러 변수가 동시에 참조할 수 있다

**C**

```javascript
int a;   // 정수형 변수 선언
a = 100; // 정수값 할당
a = 200; // 정수값 재할당
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/230351_TzgYVW7iE93tlzLApV?q=80&s=1280x180&t=outside&f=webp)

```javascript
int a, b; // 정수형 변수 선언
a = 100;  // 정수 값 할당
b = a;    // a의 값을 b에 할당
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/230425_LRvRPFS6fCtMPcPAxN?q=80&s=1280x180&t=outside&f=webp)

**Python**

```javascript
a = 100 # 객체 생성
# 객체에 대한 참조 변수 a
a = 200 # 객체 재할당
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/230357_2tzkQBETDaHFcafBKz?q=80&s=1280x180&t=outside&f=webp)

```javascript
a = 100 # 100 객체 생성과 참조
b = a   # 100 객체의 참조

```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/230429_AHWjaCgANVnOctCFfd?q=80&s=1280x180&t=outside&f=webp)

### 문자열 생성

```javascript
"Hello World"   # 큰따옴표로 양쪽 둘러싸기
'Python is fun' # 작은 따옴표로 양쪽 둘러싸기
"""Life is too short, You need python""" # 큰따옴표 3개를 연속으로 사용
'''Life is too short, You need python''' # 작은따옴표 3개를 연속으로 사용
```

**문자열에 따옴표 포함하는 경우**

```javascript
food = "Python's favorite food is perl"  # 작은 따옴표의 경우 큰따옴표와 함께 사용
food = 'Python\'s favorite food is perl' # 역슬래시를 사용한 경우

say = '"Python is very easy." he says.'   # 큰 따옴표의 경우 작은따옴표와 함께 사용
say = "\"Python is very easy.\" he says." # 역슬래시를 사용한 경우
```

**여러 줄인 문자열을 대입하는 경우**

```javascript
multiline = "Life is too short\nYou need python" # \n을 사용하여 줄바꿈

# 작은 따옴표 3개 사용
multiline='''                                    
... Life is too short
... You need python
... '''

# 큰 따옴표 3개 사용
multiline="""
... Life is too short
... You need python
... """
```

**이스케이프 코드**

- 프로그래밍할 떄 사용할 수 있도록 미리 정의해둔 ‘문자 조합’

| **코드** | **설명** |
| --- | --- |
| `\n` | 문자열 안에서 줄을 바꿀 때 사용 |
| `\t` | 문자열 사이에 탭 간격을 줄 때 사용 |
| `\\` | \를 그대로 표현할 때 사용 |
| `\'` | 작은따옴표(')를 그대로 표현할 때 사용 |
| `\"` | 큰따옴표(")를 그대로 표현할 때 사용 |
| `\r` | 캐리지 리턴(줄 바꿈 문자, 커서를 현재 줄의 가장 앞으로 이동) |
| `\f` | 폼 피드(줄 바꿈 문자, 커서를 현재 줄의 다음 줄로 이동) |
| `\a` | 벨 소리(출력할 때 PC 스피커에서 '삑' 소리가 난다) |
| `\b` | 백 스페이스 |
| `\000` | 널 문자 |

### 문자열 연산

**문자열 더해서 연결**

```javascript
head = "Python"
tail = " is fun!"
print(head + tail) # Python is fun!
```

**문자열 곱하기**

```javascript
a = "python"
a * 2 # pythonpython
```

**문자열 길이 구하기**

```javascript
a = "Life is too short"
len(a) # 17
```

**문자열 인덱싱과 슬라이싱**

```javascript
a = "Life is too short, You need Python"

# 문자열 인덱싱 - 0부터 시작
a[3]  # 'e'
a[-1] # 'n'
a[1] = a # 특정 인덱스의 글자를 변경할 수도 있음

# 문자열 슬라이싱
b = a[0:5] # 마지막은 포함하지 않음
b          # 'Life'
```

### 문자열 포매팅 String Formatting

- 문자열에서 특정한 값을 바꿔야 할 경우 사용

**% 사용**

```javascript
############################# 기본 사용법 #############################

# 정수 및 문자열 삽입 - 정수는 %d,문자열은 %s
"I eat %d apples." % 3      # 'I eat 3 apples.'
"I eat %s apples." % "five" # 'I eat five apples.'

# 변수 값 삽입
number = 3
"I eat %d apples." % number # 'I eat 3 apples.'

# 두 개 이상의 값을 삽입
number = 3
day = "three"
"I ate %d apples. so I was sick for %s days." % (number, day)

############################# 정렬, 소수점 #############################

# 정렬과 공백
"%10s" % "hi"       # '        hi': 전체 길이가 10인 문자열 오른쪽 정렬
"%-10sjane." % 'hi' # 'hi        jane.': 전체 길이가 10인 문자열 왼쪽 정렬

# 소수점 표현
"%0.4f" % 3.42134234 # '3.4213': 소수점 네 번째 자리까지만 표현
"%10.4f" % 3.42134234 # '    3.4213': 전체 길이가 10인 문자열 공간에 오른쪽 정렬
```

**문자열 포맷 코드**

| **코드** | **설명** |
| --- | --- |
| `%s` | 문자열(String) |
| `%c` | 문자 1개(character) |
| `%d` | 정수(Integer) |
| `%f` | 부동소수(floating-point) |
| `%o` | 8진수 |
| `%x` | 16진수 |
| `%%` | Literal % (문자 % 자체) |

**format 함수 사용**

```javascript
############################# 기본 사용법 #############################
"I eat {0} apples".format(3)      # 'I eat 3 apples'
"I eat {0} apples".format("five") # 'I eat five apples'

# 숫자 값을 가진 변수 대입
number = 3
"I eat {0} apples".format(number) # 'I eat 3 apples'

# 2개 이상의 값 대입
number = 10
day = "three"
"I ate {0} apples. so I was sick for {1} days.".format(number, day)
# 'I ate 10 apples. so I was sick for three days.'

# 이름으로 넣기
"I ate {number} apples. so I was sick for {day} days.".format(number=10, day=3)
# 'I ate 10 apples. so I was sick for 3 days.'

# 인덱스와 혼용해서 사용
"I ate {0} apples. so I was sick for {day} days.".format(10, day=3)
# 'I ate 10 apples. so I was sick for 3 days.'

############################# 정렬, 소수점 #############################

# 정렬
"{0:<10}".format("hi") # 왼쪽 정렬
"{0:>10}".format("hi") # 오른쪽 정렬
"{0:^10}".format("hi") # 가운데 정렬

# 공백 채우기
"{0:=^10}".format("hi") # '====hi===='
"{0:!<10}".format("hi") # 'hi!!!!!!!!'

# 소수점 표현
y = 3.42134234
"{0:0.4f}".format(y) # '3.4213'
```

**f-string**

- Python 3.6에서 도입된 새로운 문자열 포메팅 방법 (Formatted String Literals)

- 문자열 내에서 `{}`를 사용하여 변수나 표현식을 직접 삽입 가능

```javascript
############################# 기본 사용법 #############################

name = "Alice"
print(f"Hello, {name}") # 출력: Hello, Alice

############################# 표현식 사용 #############################

# f-string 안에는 직접적으로 표현식 사용 가능 -> 계산, 함수 호출 등도 가능
age = 20
print(f"Next year, you will be {age + 1}.") # 출력: Next year, you will be 21.

def great(name):
    return f"Hello, {name}"

print(great("Alice")) # 출력 :Hello, Alice

############################# 포매팅 지정자 사용 #############################
# {} 내부에 :를 사용하요 포맷팅 지정 가능
# 소수점 아래 자릿수 지정, 정렬 방법 지정 등 포메팅 가능

num = 3.14159
print(f"{num: .2f}") # 출력: 3.14

name = "Alice"
print(f"{name:>10}") # 출력:     Alice
print(f"{name:<10}") # 출력:Alice    
print(f"{name:^10}") # 출력:  Alice   

```

**f-string & format 함수 중괄호 표현**

```javascript
print(f"My set is {{1, 2, 3}}.") # 출력: My set is {1, 2, 3}.

x = 10
print(f"My set is {{{x}}}.") # 출력: My set is {10}.
```

- `{}` 안에 표현식을 넣어 리터럴 문자 `{`, `}`로 표현하고 싶다면 `{{` 또는 `}}`를 사용

- `{}`로 표현식을 나타내면서 `{}`를 리터럴 문자로 써야 하는 경우 중괄호를 세 번 사용

### 문자열 관련 함수

| **함수** | **역할** | **예시** |
| --- | --- | --- |
| `count` | 문자 개수를 리턴 | a.count(’b’) |
| `find` | 문자가 처음으로 나온 위치를 반환 | a.find('b') |
| `index` | 문자가 처음으로 나온 위치를 반환 | a.index(’t’) |
| `join` | 문자열의 문자 사이에 삽입 | ",".join('abcd') |
| `upper` | 소문자를 대문자로 바꾸기 | a.upper() |
| `lower` | 대문자를 소문자로 바꾸기 | a.lower() |
| `lstrip` | 왼쪽 공백 지우기 | a.lstrip() |
| `rstrip` | 오른쪽 공백 지우기 | a.rstrip() |
| `strip` | 양쪽 공백 지우기 | a.strip() |
| `replace` | 문자열 바꾸기 - replace(바뀔_문자열, 바꿀_문자열) | a.replace(”Life”, “Your leg”) |
| `split` | 괄호 안에 아무값도 넣지 않으면 공백을 기준으로 문자열 구분  괄호 안에 특정 값이 있을 경우에는 괄호 안의 값을 구분자로 해서 문자열을 구분 | a.split() b.split(’:’) |

### 리스트 생성

```javascript
a = list() # 비어있는 리스트
a = []
b = [1, 2, 3]
c = ['Life', 'is', 'too', 'short']
d = [1, 2, 'Life', 'is']
e = [1, 2, ['Life', 'is']]
```

- 대괄호 `[]`로 감싸주고 각 요솟값을 쉼표 `,`로 구분

**리스트의 인덱싱**

```javascript
a = [1, 2, 3]
a[0]  # 1
a[-1] # 3
```

```javascript
a = [1, 2, 3, ['a', 'b', 'c']]
a[3]     # ['a', 'b', 'c']
a[-1][0] # 'a'
```

**리스트의 슬라이싱**

```javascript
a = [1, 2, 3, 4, 5]
a[0:2]    # [1, 2]
b = a[:2] # [1, 2]
c = a[2:] # [3, 4, 5]
```

### 리스트 연산

**리스트 더하기**

```javascript
a = [1, 2, 3]
b = [4, 5, 6]
a + b # [1, 2, 3, 4, 5, 6]
```

**리스트 반복하기**

```javascript
a = [1, 2, 3]
a * 3 # [1, 2, 3, 1, 2, 3, 1, 2, 3]
```

**리스트 길이**

```javascript
a = [1, 2, 3]
len(a) # 3
```

### 리스트의 수정과 삭제

```javascript
# 리스트 값 수정
a = [1, 2, 3]
a[2] = 4 # [1, 2, 4]

# 리스트 요소 삭제
a = [1, 2, 3]
del a[1] # [1, 3]
del a[2:] # [1, 2]
```

### 리스트 관련 함수

| **함수** | **역할** | **예시** |
| --- | --- | --- |
| `append` | 리스트에 요소 추가 | a.append(4) a.append([5, 6]) |
| `sort` | 리스트의 요소를 순서대로 정렬 | a.sort() |
| `reverse` | 리스트를 역순으로 뒤집음 | a.reverse() |
| `index` | 리스트에 x값이 있으면 인덱스 값을 리턴 | a.index(3) |
| `insert` | 리스트의 a번째 위치에 b를 삽입 - insert(a, b) | a.insert(0, 4) |
| `remove` | 리스트에서 첫 번째로 나오는 값을 삭제 | a.remove(3) |
| `pop` | 리스트의 맨 마지막 요소를 리턴, 그 요소는 삭제 pop(x)는 x번째 요소를 리턴, 그 요소 삭제 | a.pop() a.pop(3) |
| `count` | 리스트 안에 x가 몇 개 있는지 조사하여 개수 리턴 | a.count(1) |
| `extend` | x에는 리스트만 올 수 있으며, 원래 a 리스트에 x 리스트를 더함 | a.extend(x) |

### 리스트 복사

**같은 객체를 가리키는 경우**

```javascript
a = [1, 2, 3]
b = a  # b는 a와 같은 객체를 가킴
a is b # a와 b가 가리키키는 객체가 같을 까? -> True
```

**다른 객체를 가리키는 경우**

```javascript
# 방법 1 - [:]
a = [1, 2, 3]
b = a[:]

```

```javascript
# 방법 2 - copy
from copy import copy
a = [1, 2, 3]
b = copy(a)
```

- a 리스트 값을 바꿔도 b 리스트에 영향 X

### C vs Python

- 파이썬의 리스트는 타 언어의 배열과 비슷하게 보인다

- 하지만 하나의 리스트에 서로 다른 자료형의 항목을 포함할 수 있다
- (리스트, 딕셔너리 등을 포함할 수 있다)

- 매우 강력한 기능이 있는 자료형

**C**

```javascript
// 배열의 선언과 초기화
int a[3] = {10, 200, 300};
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231241_K2ycLojuHAVayTV80i?q=80&s=1280x180&t=outside&f=webp)

- 배열 원소의 크기는 int형으로 고정

**Python**

```javascript
# 리스트 객체 생성
a = [100, 200, 300]
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231307_BhdmfqRI8ONz1hMoBa?q=80&s=1280x180&t=outside&f=webp)

- 서로 다른 자료형도 가능

- 리스트 요소는 참조형

**Python  리스트의 덧셈과 재할당**

```javascript
a = [1, 2, 3, 4] # 리스트 객체 생성
a = a + [5]      # 리스트 객체의 재바인딩
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231330_3kWGSOO9Nzk3xVPpsp?q=80&s=1280x180&t=outside&f=webp)

- 리스트 객체는 변경가능 mutable 객체

    - int, tuple, str 객체는 변경불가능 immutable 객체

- 리스트의 `append()` 메소드는 객체의 내용을 변경

- 리스트의 `+` 연산은 객체로 복사해서 재바인딩

```javascript
a = [1, 2, 3]
b = a # b가 [1, 2, 3] 리스트를 참조 (사본을 만들지 않음)
b.append(4) # 리스트는 변경 가능 mutable -> a, b의 결과가 같다
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231347_wnSvVIYwfbI3CKFHZU?q=80&s=1280x180&t=outside&f=webp)

- 리스트는 변경 가능 자료형 mutable 객체

- 객체 a를 다른 객체 b에 할당 할 때 데이터의 복사가 발생하지 않는다  → 효율성 증대

### 얕은 복사, 깊은 복사

- 리스트나 클래스의 인스턴스와 같은 복합 객체에 대해서만 적용

| **얕은 복사** | 새 복합 객체를 만들고 원본 객체 내에 있는 오브젝트에 대한 **참조 삽입** |
| --- | --- |
| **깊은 복사** | 새 복합 객체를 만들고 원본 객체 내에 있는 객체에 대한 복사를 **재귀적으로 삽입** |

**단순 할당**

```javascript
a = [[1, 2], [3, 4]]
b = a
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231517_G6HnK7rZ2sfsGYSQuc?q=80&s=1280x180&t=outside&f=webp)

**얕은 복사 shallow copy**

```javascript
a = [[1, 2], [3, 4]]
b = a[:]
a[0] = [10, 20]
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231533_v6S4GzlFnxXf7v92GI?q=80&s=1280x180&t=outside&f=webp)

**깊은 복사 Deep Copy**

```javascript
import copy
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
a[0][0] = 10
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231550_177qxqXZoWaSJffkwv?q=80&s=1280x180&t=outside&f=webp)

- 재귀적인 객체에 대한 참조는 재귀 루프에 빠질 수 있다

- 두 복사본이 공유하려고 한 데이터에 대해 너무 많은 복사를 할 수 있다

### 다차원 리스트

```javascript
# 방법 1
board = [[0] * cols] * rows
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231614_KwMIgNMgopjAJ8WXkC?q=80&s=1280x180&t=outside&f=webp)

```javascript
# 방법 2
board = [[0] * cols for _ in range(rows)]
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231620_29pezjjazCQFsBK28L?q=80&s=1280x180&t=outside&f=webp)

- 방법 1은 객체의 수가 적고 참조도 적게 하기 때문에 방법 2보다 빠르다

```javascript
board[0][0] = 1
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250127/231638_I7NR3KSuv7xR6utcFE?q=80&s=1280x180&t=outside&f=webp)

- 하지만 값을 바꿀 때 차이가 존재한다

### 리스트 축약 표현

- 반복가능 객체를 이용하여 쉽게 리스트를 생성할 수 있는 기능

- map, filter 기능 구현 가능

- 람다식의 본체가 될 식을 그대로 사용하기 때문에 따로 람다함수를 정의할 필요가 없다

- 리스트뿐만 아니라 집합과 같은 반복 가능한 모든 객체에 대해 적용할 수 있다

- 축약 표현은 많은 장점을 가지지만 조건이 많거나 표현식이 복잡해지면 이해하기 어렵다

**문법**

```javascript
[{표현식} for {변수} in {반복자/연속열} if {조건 표현식}]
[{표현식} for {변수} in {반복자/연속열}]
```

- `{표현식}` : 반복가능 객체의 요소에 대해 적용되는 수식 → **맵 map** 기능

- `for {변수} in {반복자/연속열}`: 반복가능 객체의 순환하는 기능

- `if {조건 표현식}`: **필터 filter**의 기능, 생략 가능

**예시**

```javascript
a = [1, 2, 3, 4, 5, 6, 7] # 연속된 값을 가지는 리스트

##################### 아래 결과가 모두 같음 #####################

# 맵과 람다 함수를 이용한 리스트의 제곱
a = list(map(lambda x: x**2, a)) # 리스트의 각 요소에 대하여 람다 함수 적용

# 리스트 축약 표현식을 이용한 리스트의 제곱 구하기
a = [x**2 for x in a] # 리스트의 각 요소에 대하여 x**2를 적용

# 리스트 축약 표현식과 range를 이용한 리스트의 제곱 구하기
a = [x**2 for x in range(1, 8)]

###############################################################

print(a) # [1, 4, 9, 16, 25, 36, 49]
```

**map() 함수와 리스트 축약 표현**

- map() 함수는 map 객체를 생성, 축약 표현을 사용하면 리스트 객체를 바로 생성 가능

- 간결한 표현으로 강력한 기능을 사용 가능

- map() 함수를 사용하는 것보다 속도가 더 빠르다

- 필터링까지 할 수 있어 filter() 함수의 역할도 수행

**if 조건식을 이용한 필터링**

```javascript
# list() 함수, filter() 함수, 람다 함수를 이용한 필터링
ages = [34, 39, 20, 18, 13, 54]
adult_ages = list(filter(lambda x: x>=19, ages))
print('성년 리스트 : ', adult_ages)

# 리스트 축약표현을 이용한 필터링
ages = [34, 39, 20, 18, 13, 54]
print('성년 리스트 : ', [x for x in ages if x >= 19])

# list() 함수, filter() 함수, 람다 함수를 이용한 음수 필터링
n_list = [-30, 45, -5, -90, 20, 53, 77, -36]
minus_list = list(filter(lambda x: x<0, n_list))
print('음수 리스트: ', minus_list)

# 리스트 축약 표현과 if조건식을 이용한 필터링
n_list = [-30, 45, -5, -90, 20, 53, 77, -36]
minus_list = [x for x in n_list if x < 0]
print('음수 리스트 : ', minus_list)
```

- 반복문을 통해 할당된 각각의 x에 대하여 `if x>=19`라는 조건식 필터 적용

**이중 for 루프 구현**

```javascript
product_xy = [x * y for x in [1, 2, 3] for y in [2, 4, 6]]
print(product_xy)
```

```javascript
t1 = ()
t2 = (1,)       # 1개의 요소만을 가질 때는 요소 뒤에 쉼표를 붙인다
t3 = (1, 2, 3)  # 튜플은 소괄호로 둘러싼다
t4 = 1, 2, 3    # 소괄호를 생략할 수 있다
t5 = ('a', 'b', ('ab', 'cd'))
```

- 리스트는 대괄호 `[]`, 튜플은 소괄호 `()`로 둘러싼다

- 리스트는 생성, 삭제, 수정이 가능하지만 튜플은 요솟값을 바꿀 수 없다

**튜플 요솟값 삭제, 변경**

```javascript
t1 = (1, 2, 'a', 'b')
del t1[0]
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: 'tuple' object doesn't support item deletion

t1 = (1, 2, 'a', 'b')
t1[0] = 'c'
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: 'tuple' object does not support item assignment
```

- 튜플의 요솟값을 삭제 혹은 변경하려고 하면 오류가 발생한다

**튜플 인덱싱 및 슬라이싱**

```javascript
# 튜플 인덱싱
t1 = (1, 2, 'a', 'b')
t1[0] # 1
t1[3] # 'b'

# 튜플 슬라이싱
t1 = (1, 2, 'a', 'b')
t1[1:] # (2, 'a', 'b')
```

**튜플 연산**

```javascript
# 튜플 더하기
t1 = (1, 2, 'a', 'b')
t2 = (3, 4)
t3 = t1 + t2 # (1, 2, 'a', 'b', 3, 4)

# 튜플 곱하기
t2 = (3, 4)
t3 = t2 * 3 # (3, 4, 3, 4, 3, 4)

# 튜플 길이
t1 = (1, 2, 'a', 'b')
len(t1) # 4
```

```javascript
dic = {'name': 'pey', 'phone': '010-9999-1234', 'birth': '1118'}
```

- 리스트, 튜플 처럼 순차적 접근이 아닌 key를 통해 value를 얻는다

- key, value 여러 쌍이 `{}`로 둘러싸여 있으며, 쉼표로 구분된다

- value에 리스트를 넣을 수 있다

**딕셔너리 쌍 추가, 삭제**

```javascript
# 딕셔너리 쌍 추가
a = {1: 'a'}
a[2] = 'b'        # {1: 'a', 2: 'b'}
a['name'] = 'pey' # {1: 'a', 2: 'b', 'name': 'pey'}
a[3] = [1, 2, 3]  # {1: 'a', 2: 'b', 'name': 'pey', 3: [1, 2, 3]}

# 딕셔너리 쌍 삭제
del a[1]          # {2: 'b', 'name': 'pey', 3: [1, 2, 3]}
```

**딕셔너리 사용**

```javascript
# Key에서 Value 얻기
grade = {'pey': 10, 'julliet': 99}
grade['pey']     # 10
grade['julliet'] # 99
```

**딕셔너리 주의사항**

```javascript
a = {1:'a', 1:'b'} # 1:'a'는 무시다
```

- Key는 고유한 값 → 하나를 제외한 나머지는 모두 무시된다

- Key에 리스트 X, 튜플 O

### 딕셔너리 관련 함수

| **함수** | **기능** | **예시** |
| --- | --- | --- |
| `keys` | 딕셔너리의 Key만을 모아 `dict_keys` 객체 리턴 | a.keys()  for k in a.keys(): list(a.keys()) |
| `values` | 딕셔너리의 Value만을 모아 `dict_values` 객체 리턴 | a.values() |
| `items` | 딕셔너리의 Key, Value 쌍을 튜플로 묶은 `dict_items` 객체 리턴 | a.items() |
| `clear` | 딕셔너리 안의 모든 요소 삭제 | a.clear() |
| `get` | 주어진 Key에 대응되는 Value를 리턴  Key 값이 없을 경우 가져올 디폴트 값을 지정할 수 있음 | a.get(’name’) a.get(’nokey’, ‘default’) |
| `in` | 주어진 Key가 딕셔너리 안에 있는지 True/Flase를 리턴 | ‘name’ in a |

```javascript
s = set()
s1 = set([1, 2, 3]) # {1, 2, 3}
s2 = set("Hello")   # {'e', 'H', 'l', 'o'}
```

- `set` 키워드를 사용해 만들 수 있다

- set()의 괄호 내부에 리스트를 입력하여 만들거나 문자열을 입력하여 만들 수 있다

- 중복을 허용하지 않으며, 순서가 없다
- → 인덱싱으로 접근하려면 리스트나 튜플로 변환 후 가능

**교집합, 합집합, 차집합**

```javascript
s1 = set([1, 2, 3, 4, 5, 6])
s2 = set([4, 5, 6, 7, 8, 9])

# 교집합
s1 & s2             # {4, 5, 6}
s1.intersection(s2) # {4, 5, 6}

# 합집합
s1 | s2      # {1, 2, 3, 4, 5, 6, 7, 8, 9}
s1.union(s2) # {1, 2, 3, 4, 5, 6, 7, 8, 9}

# 차집합
s1 - s2           # {1, 2, 3}
s1.difference(s2) # {1, 2, 3}
```

**집합 관련 함수**

| **함수** | **기능** | **예시** |
| --- | --- | --- |
| `add` | set 자료형에 값을 추가 | s.add(4) |
| `update` | 값 여러 개 추가 | s.update([4, 5, 6]) |
| `remove` | 특정 값 제거 | s.remove(2) |

```javascript
a = True
b = False
type(a) # <class 'boo'>
1 == 1  # True
```

- 참 True, 거짓 False을 나타내는 자료형

- 조건문의 리턴값으로도 사용된다

**참 vs 거짓**

| **값** | **참 or 거짓** | **값** | **참 or 거짓** |
| --- | --- | --- | --- |
| “python” | 참 | {’a’: 1} | 참 |
| “” | 거짓 | {} | 거짓 |
| [1, 2, 3] | 참 | 1 | 참 |
| [] | 거짓 | 0 | 거짓 |
| (1, 2, 3) | 참 | None | 거짓 |
| () | 거짓 |  |  |

- 문자열, 리스트, 튜플, 딕셔너리 등은 값이 비어있으면 거짓, 비어있지 않으면 참

- 숫자는 값이 0일 때 거짓, 0이 아니라면 참

**제어문에 사용**

```javascript
a = [1, 2, 3, 4]

while a:
    print(a.pop())
```

- a의 모든 요소를 꺼내서 빈 리스트가 되면 거짓이 되어 while문 종료

```javascript
if []:
    print("참")
else:
    print("거짓")
```

- `[]` 는 빈 리스트이기 때문에 거짓

**불 연산**

```javascript
bool('python') # True
bool('')       # False
```

## 컴프리헨션

---

- 기존 시퀀즈 sequence, 이터러블 iterable, 또는 다른 표현식들로부터 새로운 시퀀스를 생성하는 간결하고 가독성이 있는 방법

- 몇 가지 타입의 컴프리 헨션 사용 가능: 리스트 컴프리헨션, 딕셔너리 컴프리헨션, 세트 컴프리헨션, 그리고 제너레이터 컴퓨리헨션

> 컴프리헨션 및 google convertion은 2중 for문 등을 사용하지 않도록 권고

**리스트 컴프리헨션**

```javascript
squares = [x**2 for x in range(10)] # 0부터 9까지의 제곱 리스트 생성

# 0부터 9까지의 짝수의 제곱 리스트 생성
even_squares = [x**2 for x in range(10) if x % 2 == 0] 

[f'{i} X {j} = {i * j}' for i in range(2, 10) for j in range(1, 10)]
```

- 대괄호 `[]` 안에 `for`문과 `if`문을 사용하여 리스트 생성

**딕셔너리 컴프리헨션**

```javascript
square_dict = {x: x**2 for x in range(5)} # 0부터 4까지의 수를 키로, 그 제곱을 값으로 딕셔너리 생성
square_dict

books = ['python', 'javascript', 'html/css']
book_dict = {book: idx for idx, book in enumerate(books)}
book_dict

# 문제: {'python': 10000000, 'javascript': 24000000, 'html/css': 39000000}와 같은 형태로 출력
books = [('python': 1000, '10000원'), ('javascript', 2000, '120000원'), ('html/css', 3000, '13000원')]
```

- 중괄호 `{}` 안에 `for`문과 선택적 `if`문을 사용하여 딕셔너리 생

- `key:value` 형태를 사용

**세트 컴프리헨션**

```javascript
odd_set = {x for x in range(10) if x % 2 != 0} # 0부터 9까지의 홀수
```

- 중괄호 `{}` 안에 `for`문과 선택적 `if`문을 사용하여 세트를 생성

**제너레이터 컴프리헨션**

```javascript
square_gen = (x **2 for x in range(10)) # 0부터 9까지의 제너레이터

gen = (i for i in range(2, 100000000, 2))
for i, j in zip(range(10), gen):
    print(i, j)
```

- 소괄호 `()` 안에 `for`문과 `if`문을 사용하여 제너레이터 객체 생성

- 제너레이터는 반복을 위한 이터러블이지만, 모든 값을 메모리에 저장하지 않고 필요할 때 생성한다

## Collections 모듈

---

- 다양한 형태의 컨테이너를 제공, 데이터 조작을 쉽고 효율적으로 할 수 있도록 한다

- deque와 Coutner는 알고리즘 문제 풀이에서 많이 사용

**deque**

- 양쪽 끝에서 요소를 추가하거나 제거할 수 있는 스레드-안전한 양방향 큐입니다.

```javascript
from collections import deque

d = deque()
d.append('a')     # 오른쪽 끝에 추가
d.appendleft('b') # 왼쪽 끝에 추가
d.pop()           # 오른쪽 끝 요소 제거
d.popleft()       # 왼쪽 끝 요소 제거
d.rotate(1)       # 오른쪽 끝 요소를 왼쪽 끝 요소로
```

**Counter**

- 요소의 개수를 세는 데 사용되는 컬렉션

```javascript
from collections import Counter

c = Counter('hello world')
print(c) # 출력: Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
```

**OrderedDict**

- 키의 삽입 순서를 기억하는 딕셔너리

> Python 3.7부터는 딕셔너리가 삽입 순서를 기억하게 되었습니다.

이 모듈은 잘 사용되지 않습니다.

```javascript
from collections import OrderedDict

od = OrderedDict()
od['a'] = 1
od['b'] = 2
print(od) # 출력: OrderedDict([('a', 1), ('b', 2)])
```

For the site tree, see the [root Markdown](https://slashpage.com/yerim-devnote.md).
