Python 기본
파이썬에서 기본적으로 알아야 하는 부분과, 놓치기 쉬운 부분에 대해서 리마인드 하는 시간을 가져보자.
변수 선언
- 동적 타입 언어로, 변수의 타입을 지정하지 않는다.
- float에서 0은 생략이 가능함 ex) .1 = 0.1, 10.0 = 10.
- char type이 없다.
입출력
print("Hello", "World", sep = "-", end="!") # 출력값 : Hello-World!
name = input() # input()을 통한 입력 방식은 기본적으로 무조건 문자열로 저장됨.
age = int(input()) # 이와 같이 필요에 따라 형변환 진행
자료 구조
list
- 가변적이며, 순서가 있는 데이터의 집합
- List() 함수 혹은 대괄호[]를 사용
- 주요 함수 : append, extend, insert, remove, pop, index, count, sort, reverse
slicing
- [start : stop: step] -> start가 0인경우 생략 가능 / step이 1인경우 :step 생략 가능.
- [1: stop : 1] -> stop에 최대보다 큰 index 값이 들어가면 자동으로 가장 리스트의 끝까지로 처리 (보통 이런 경우 생략)
- step에 -1을 사용하는 경우도 존재. (역순)
- fruits[1] -> 'banana' (문자열 반환) / fruits[1:2] -> ['banana'] (리스트 반환)
즉 indexing은 차원을 하나 낮추고 슬라이싱은 차원을 유지하는것을 확인해볼 수 있다.
list 에서 '차원'을 언급하지 않는 이유?
a = [[10,20], 40] -> 2차원? 정의 불가.
list는 무조건 1차원으로 취급. 내부 묶음은 그저 묶음일 뿐.
tuple
- 불변적이며, 순서가 있는 데이터의 집합
- tuple() 함수 혹은 소괄호()를 사용
set
- 순서가 없고, 중복을 허용하지 않는 데이터의 집합
- set() 함수 혹은 중괄호{}를 사용
- 주요 함수 : add, remove, union, intersection, difference, symmetric_difference
dict
- 키와 값의 쌍으로 구성된 데이터의 집합
- 키는 수정/추가/삭제 불가능한(immutable) 객체를 사용
- 문자열, (10:20)과 같은 값도 키로 사용 가능
- dict() 함수 혹은 키와 값의 한 쌍을 가지는 중괄호 {키:값}을 사용
- 주요 함수 : get, keys, values, items, update, pop
dictionary a에 대해서 a[key]와 a.get(key)의 차이점은?
a[key]에 값이 없는 경우 에러가 발생.
a.get(key)는 값이 없는 경우 None을 return. 지정된 default값이 있다면 이를 반환.
+컨셉적으로는 dict에 순서가 없지만, 실제로는 순서가 존재함 (순차 탐색 가능)
제어문
조건문
- if / elif / else
name = '홍길동'
b = name if name else '아무개' # 삼항연산자
print(b) # 출력값 : 홍길동
파이썬의 모든 객체는 참/거짓을 판단할 수 있다.
- 숫자 : 0외에는 모두 참
- 자료 구조 : empty 외에는 모두 참
반복문
- 시퀀스(리스트/튜플/문자열등)나 반복 가능한(iterable)객체의 각 요소에 대해 반복
- membership 연산자와 range, enumerate를 함께 자주 사용
fruits = ['banana', 'apple', 'cherry']
for fruit in fruits:
print(fruit)
# 출력: banana, apple, cherry
for idx, fruit in enumerate(fruits):
print(idx, fruit)
# 출력: 0 banana, 1 apple, 2 cherry
dict = {'2': 0, '1': 1}
for i in dict.keys():
print(i)
# 출력 : 2 1 # .keys()를 없애도 동일하게 출력됨. (dict는 iterable 하다!)
list(enumerate(['apple','banana','cherry']))
# 출력 : [(0, 'apple'), (1, 'banana'), (2, 'cherry')]
list comprehension (dictionary, set에도 존재)
results = [i for i in range(3)]
results
함수
입력 값
- 가변 매개변수 : 함수가 가변적인 개수의 인자를 받도록 하는 매개변수
- *args : 위치 인자 (인자의 순서에 따라 값과 매개변수에 할당 - 튜플로 저장)
- **kwargs : 키워드 인자 (정의된 매개변수 이름을 명시하여, 인자의 순서와 관계없이 값을 전달 - 딕셔너리로 저장)
- 매개변수 사용 시 위치 인자 앞에 키워드 인자가 나오면 에러 발생 !!!
def func(c, d, *a, **b):
return a, b
func(c=20, 10, a=20)
c가 함수정의시 인자에 있는 경우는 해당 값으로 사용되지만, *a, **b와 같이 *와 함께 사용되는 경우 그 변수명은 의미 없음.
a=10으로 넘겨주었지만 키워드 인자로 인식됨.
함수명?
def func(): ...
func?
아래 4가지의 출력값을 확인해볼 수 있다.
- Signature: 인자 목록
- DocString: """~"""과 같이 작성된 문서 문자열 설명
- File: 함수가 정의된 파일의 경로
- Type: 객체의 타입(자료형)
반환 값
- 여러 개의 값을 튜플 형태로 반환하고, 분해하여 받을 수 있다.
익명 함수
- lambda 키워드를 사용
- 간결하고 한 줄로 작성되며, 일반적으로 간단한 연산이나 짧은 함수를 정의할 때 사용
- 표현식 형식을 가지며, 인자는 여러 개일 수 있다.
numbers = [1,2,3,4,5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # 출력 : [1,4,9,16,25]
모듈과 패키지
모듈
- Python에서는 .py 확장자를 가진 파일이 모듈이 될 수 있다.
- 모듈을 사용하려면 import module 구문을 사용하여 메모리로 가져올 수 있다.
- 특정 함수나 변수만 가져오려면 from module import function 구문을 사용할 수 있다.
패키지
- 여러 모듈을 하나의 디렉터리로 구상한 것
- 계층 구조를 가질 수 있어 코드를 체계적으로 관리할 수 있다.
- 디렉터리 내에 __init__.py 파일을 포함하며, 패키지로 인식되도록 한다.
- 패키지를 가져오려면 import package.module 구문을 사용한다.
그 외
encoding/decoding <-> Hash 차이점?
원복이 가능한가?
문자열 replace 함수는 원본을 변경하는가?
X. 원본값에서 replace를 수행한 새로운 값을 반환할 뿐.
Unpacking : 시퀀스 또는 iterable한 객체에 대해 값을 분해하는것이 가능
a, b = (0, 'apple')
print(a) # 0
print(b) # apple
a, [b, c] = [10, [20, 30]]
print(a, b, c) # 10 20 30
추가 궁금증
함수와 메서드의 차이점
- 함수 (Function)
- 독립적으로 정의되며, 이름으로 호출
- 인자를 받을 수도 있고, 반환값이 없을 수도 있음
- ex) len(), print() ...
- 메서드 (Method)
- 클래스 내부에 정의된 함수이며, 반드시 객체(클래스)와 연관되어 .을 통해 사용
- 호출 시 객체 자신(self)가 첫 번째 인자로 자동 전달
- ex) list.append(), str.upper() ...
iter과 next ?
iter과 next함수를 알아보기에 앞서 iterator와 iterable 한 객체의 차이점에 대해 알아보자.
iterator란 무엇인가?
- 반복 가능한 객체에서 하나씩 값을 꺼낼 수 있는 객체 (값을 꺼내는 방식이기에 재순회 불가)
- __iter__()와 __next__() 메서드를 가지고 있음. (__는 매직 메서드임을 명시하기 위함.)
- for문 내부 동작에서 사용 (대상이 iterator이든 iterable한 객체이든 iter()을 감싸서 사용)
- iter() 사용 시 자기 자신을 반환 (동일 객체, 동일 메모리 주소)
- next() 호출할 때마다 다음 값을 하나씩 순서대로 반환. (더 이상 꺼낼 값이 없다면, StopIteration예외 발생)
- next(iterator, 기본값)과 같이 사용한다면 더 이상 꺼낼 값이 없을 때 기본값 반환.
"iterable한 객체"
list, dictionary, set, str...가 해당하며 next()는 없고, iter() 메소드만 존재
next() 메서드를 사용하기 위해서는 iter()를 통해 iterator로 변환 필요
- 기본적으로 iter(literable한 객체)와 같이 사용. 그 객체의 iterator 객체 반환
- iter(callable, sentinel) 호출 가능한 객체와 반복을 끝낼 값 두 인자를 사용할수도 있음
Comprehension
"iterable한 객체"에서 새로운 리스트, 집합, 딕셔너리등을 간결하고 효율적으로 생성하기 위한 문법
[표현식 for 변수 in 반복가능객체 if 조건]
numbers = [1, 2, 3, 4, 5]
squares = [num ** 2 for num in numbers]
# 결과: [1, 4, 9, 16, 25]
even_numbers = [num for num in numbers if num % 2 == 0]
# 결과: [2, 4]
- List comprehension: 대괄호 [] 사용, 리스트 생성
- Set comprehension: 중괄호 {} 사용, 집합 생성
- Dictionary comprehension: 중괄호 {}와 key: value 사용, 딕셔너리 생성
- Generator expression: 소괄호 () 사용, 제너레이터 객체 생성
*generator : iterator를 생성해주는 함수(더 궁금하다면 yield 키워드에 대해서도 알아보자...)
Type Hint
코드에 변수, 함수 인자, 반환값등의 타입 정보를 명시적으로 표시하는 기능
def greet(name: str) -> str:
return f"Hello, {name}!"
from typing import Union
def process(item: Union[int, str]) -> None:
print(item)
타입 힌트를 작성하더라도 타입이 강제되지는 않음.
타입이 다르더라도 파이썬 인터프리터는 에러를 내지 않으며, 타입 검사는 별도의 도구로 해야 함.
협업 및 유지보수, 정적 타입 검사 도구 등에 대해 도움이 됨.