ASAC-SK플래닛 T아카데미 데이터 엔지니어

25.10.16 7일차 [ 파이썬 기초 개념 강의_(매개변수, 함수 종류, 내장함수, 외장함수, pickle, scope, 애너테이션, 모듈화, 모듈 가져오기, __name__, 예외처리)]

Datadesigner 2025. 10. 17. 17:48

오늘은 어제에 이어서

  • 매개변수 파트 정리
    • 함수의 종류
      • 내장 함수
      • 외장 함수
        • pickle
    • scope
    • 애너테이션
    • 모듈화
      • 모듈 가져오기
      • __name__
    • 예외처리

등의 내용을 공부하였다

 

내용 정리

 

요구사항
- 함수명 : add_ex
- 입력 : 가변인자 (*인자명) , x
- 처리 : 입력된 모든 인자를 합산
- 반환 : 합산 결과

def add_ex( *x ):
  print ( x , type(x))
  sum = 0
  for n in x:
    sum += n
  return sum

add_ex(1)
add_ex(1, 2)
add_ex(1, 2, 3)
출력값


(1,) <class 'tuple'>
(1, 2) <class 'tuple'>
(1, 2, 3) <class 'tuple'>
6
1. 가변인자 *x에 튜플을 대입하며 sum = 반환값이다
2. 이 때 for문을 통해서 sum에 각 값을 합산한다는 반복을 부여하고 
3. n 값이 합산된 값 sum을 반환받는다.

 

  • 매개변수, 인자 : 일반인자, 가변인자 혼용
    • 대부분 타인이 만들 라이브러리들은 이 순서를 따름
    • 일반 인자는 *필수인자*로 인식됨 -> 반드시 함수 호출 시 세팅되어야 함
def add_ex2( x , *y ) : # *y = 가변인자
  print( f'x={x} , y={y}')
add_ex2(1)
add_ex2(1, 2)
add_ex2(1, 2, 3)
출력값
x = 1, y=()
x = 1, y=(2, )
x = 1, y=(2, 3)
# 첫 번째 인자는 x로, 나머지 인자들은 가변인자로 대입되어 이러한 출력이 나온다.

 

  • 매개변수, 인자 : 인자의 기본값 부여
    • 매개변수에 기본값 부여 (함수 정의 시)
    • 해당 변수의 타입을 가이드
    • 가장 중요한 값, 가장 기본값 표기
    • 함수 사용의 편의성 증가 -> 해당 매개변수 생략 가능함 -> 기본값 적용됨
def feature_ext ( stride = 1 , padding = 'same' , shape = None ) :
  print (stride, padding, shape)

feature_ext()
feature_ext(2)
feature_ext(3, 'valid')
feature_ext(padding = 'valid')
feature_ext(shape = 4,4)
feature_ext(shape = 4,4 , padding = 'valid' , stride = 2)

출력값

1 same None
2 same None
3 valid None
1 vaild None
1 same (4, 4)
2 vaild (4, 4)

기본 인자를 제공하지 않는다면 함수 정의 시 부여된 기본값으로 출력된다.
하나하나 출력값과 대입해서 생각해본다면 어떠한 과정으로 매개변수에 인자가 들어가는지 알 수 있다.
이 때 shape 부분은 None인데 이는 어떠한 형식의 데이터도 받아들일 수 있는 Any로 나온다.

 

  • 매개변수, 인자 : keyword argument
    • 표현
      • **매개변수명
      • 통상 대부분 개발자는 **kwargs
    • 특징
      • 통상 함수 정의상 가장 마지막 매개변수로 주로 보임
      • 함수의 업그레이드를 위한 용도
      • 업그레이드, 기존 기능 유지, 신규 기능도 처리
      • 써드 파트 라이브러리 함수 확인
def add4 (**kwargs):
  print (kwargs, type(kwargs)) # 딕셔너리로 반환된다

add4
add4( name = '파이썬', age = 35)

출력값

{ } <class 'dict'>
{'name' : '파이썬' , 'age' : 35} <class 'dict>
  • 매개변수, 인자: 종합 (모든 내용 종합)
    • 매개변수 유형 모두 배치
      • 권장
  • 일반인자, 가변인자, 키워드인자 -> 순서대로 중요함!
def add5 ( a, b, *c, **kwargs):
  print ( a, b, c, kwargs)

add5 (1, 2, 3, 4, 5, 6, ppp='파이썬')

출력값은?
1 2 (3, 4, 5, 6) {'ppp' : '파이썬'}
이는 일반 인자 a b 에는 순서대로 1 과 2 가 배치되고
3, 4, 5, 6 은 가변인자 *c로
**kwargs에 키 값이 배치된것이다.

def add5 ( a, b, *c, **kwargs):
  print ( a, b, c, kwargs)

add5 ( a = 10 , ppp='파이썬', b = 100)
10 100 () {'ppp' : '파이썬'}
기본값이 없는 매개변수에는 반드시 함수 호출 시 인자값을 전달해야 한다 -> 필수 옵션

 

함수 종류
  • 내장 함수
    • 파이썬 설치하면 바로 사용 가능함
  • 외장 함수
    • 파이썬 설치 혹은 써드파트 라이브러리 (패키지) 설치 후 접근 가능
    • 특정 모듈을 가져와서, 해당 모듈 기반에서 접근
      • import random
      • # 거의 대부분 . 연산자가 보임 -> 출처 표기가 명확함
      • random.randint()
  • 사용자 정의 함수
    • 기본형
    • 람다함수 (가장 빠른 함수)
    • 데코레이터 적용된 함수
      • 순수함수, 클로저 개념 적용
      • 변수 스코프 사용 : global(전역), nonlocal(아웃터(바깥쪽)) 함수 내부에서 이너(내부) 의 함수의 변수를 사용할 때 표기)
    • 제너레이터 적용된 함수
  • 중요 내장 함수
    • 중요한것만 살피고, 필요시 찾아서 사용이 기본
  • 파일 I/O(입출력)
    • 목적
      • 파이썬 프로그램 <-> 파일(리소스, 로컬 PC내 os단에 존재, 클라우드 내 서비스 s3 등등)
      • 읽기(r), 쓰기 (w), 생성
      • 기본값 텍스트 읽고 쓰기, b(바이너리)읽고 쓰기
    • open() 
      • 파이썬 인터페이스(도구)만 제공, 실제 처리는 C/ C++이 수행, 연결고리는 싸이썬 라이브러리 처리 <- 싸이썬 오타 아니다!
    • 특징
      • I/O 수행하면 잠재적으로 오류 발생할 수 있음
        • 예외처리등 필요
      • 리소스를 오픈했으면 반드시 닫는다 (close())
        • close() 누락 방지 -> 자동 닫기 기능 제공 -> with문
# 기본 파일 생성 오픈, 닫기
# 1. 생성 및 오픈
f = open("a.txt", (w)) -> w가 쓰기를 표시하는것임
# 2. 작업
f.write('ab AB 가나 12 !@')
# 3. 닫기
f.close()
-> 이 작업을 수행하면 파일칸에 a.txt가 생기고 읽어보면
잘 출력이 된 것을 볼 수 있다.

with문을 사용한다면
as = 별칭을 붙여주는 함수와는 또 다른 기능이다
문법
대상 as 별칭

with open("a.txt" , "w") as f:
  f.write('ab AB 가나 12 !@")

실행해보면 똑같은 작업이 구동되는것을 확인할 수 있다. 그리고 자동으로 close()가 적용되어 close함수도 빠져 더욱 처리가 빠른 코드가 된것!

 

  • map()
    • 목적
      • 연속된 데이터(컬렉션 계열들 중 리스트)의 멤버를 하나씩 꺼내서 뭔가 작업(2배로 확대, 전처리 등등)
      • 데이터를 하나씩 꺼내 조작(전처리)
datas = [1, 2, 3, 4, 5]

# 요구사항 : datas의 모든 멤버의 값을 2배로 업그레이드 하시오

# 2배 곱하는 함수 정의
def double( x ):
  return x * 2 

list( map( double , datas ) ) 

출력값
[2, 4, 6, 8, 10]
map()은 쉽게 생각해서 뒤에 있는 데이터를 하나씩 꺼내서 앞에 있는 함수에 대입한다고 생각하면 된다.
그리고 list로 묶여있기 때문에 그대로 리스트에 담겨서 출력되는것

그리고 이것을 리스트 컴프리헨션으로 구한다면

[ v*2 for v in datas ]

같은 값이 출력되는것을 알 수 있다. 리스트 컴프리헨션 짱이다
순서대로 
[ v ] -> 리스트에 하나 나올 변수 제공
[ v *2 ] -> 원하는 값이 2배니까 변수에 *2
[ v*2 for v in datas ] -> 그냥 변수에 for문으로 하나씩 대입 끝 덜덜

 

  • 람다 함수
    • 가장 빠른 고속 함수
    • 사용된 곳과 한 몸으로 세팅이 됨 -> 재사용 x -> 1회성
    • lambda 매개변수 .. : 수행문이 1개여야 함, return 생략
# 람다함수로 동일한 값을 구하면?

list( map ( lambda x : x*2 ,datas))

[2, 4, 6, 8, 10]
map() 함수는 뒤의 리스트에서 앞의 수행문을 수행한다, 이 때
lambda x : x*2 는 대입받는 변수 x 에 *2를 한다는 뜻이니 그대로 출력되는 것이다.


# 람다 함수를 재사용 하려면?

two = lambda x : x*2

list (map( two , datas ) )


람다 함수를 다른 변수에 제공함으로써 람다 함수를 재사용할 수 있게 된다.

 

 

  • filter()
    • 필터링 용도 -> 데이터를 필요한 것만 추출
    • 대상에 포함될지, 말지 판단 -> 불린형 반환
datas = [1, 2, 3, 4, 5]
datas 에서 짝수만 추출하시오

def 필터 (x):
  if x%2 == 0:
    return True
  else:
    return False

list(filter(필터 , datas))

[2, 4]
평소 하던대로 각 값을 if문으로 대입하여 True이면 대입, False이면 출력하지 않는 조건문을 작성한 것이다.
여기서 기존의 조건문과 다른 점은, filter()함수를 통해서 True일때는 출력, False일때는 출력x를 반영하는 것이다.




이를 람다함수로 바꾸면
list(filter(lambda x : x%2==0 , datas))

더 간결하게 하면

list(filter(lambda x : not x%2 , datas))
지난 조건문에서 사용한 부정의 부정 not 연산자를 통해서 더 줄일 수 있다!


리스트 컴프리핸션으로는

[ even for even in datas if not even %2 ]
 완전히 줄일 수 있따.
1. [ even ] 리스트를 받아야 하고 변수 입력
2. for 문으로 datas의 데이터 even에 대입
3. if문으로 짝수만 걸러내기

 

 

 

ord()

 

알파벳 등 각 문자열의 ASCII (아스키코드)의 수치값을 찾아주는 함수

ord('a') = 97, ord('z') = 122

ord()를 이용하면 기준문자대비 얼마나 떨어져있는지 계산 가능함

ord('z') - ord('a') = 25

이를 통해 말뭉치(코퍼스) 로부터의 문자를 1개씩 추출하여 각 알파벳의 빈도수를 구할 수 있음.
이는 현재는 엄청 중요하진 않으나 추후 번역기, 등 다양한 머신러닝과 데이터 분석등에 많이 사용된다고 함.

너무 길어서 캡쳐로 ㅎ

 

  • 외장 함수
    • 써드 파트 라이브러리
    • 파이썬 설치 후 제공
      • import os
        • 파이썬 어플리케이션 종료 함수 (예시)
        • 소속. 개별내용 <- 우리가 아는 통상 파일 출처 가 보임
        • os.exit()
    • 별도 설치 후 사용
      • 별도 설치한다면 -> 패키지 관리자를 통해 설치 필요
      • pip install  패키지명
      • conda install 패키지명
!pip install  pymysql
# 파이썬은 앞에 !를 꼭 붙여야 함

 

  • pickle
    • 파이썬 자료구조, 타입, 객체 등등 그대로 보존(덤프) , 로드 후 다시 사용가능하게 처리
    • 해당 기능이 확장되어 모델 학습후 모델 덤프시 활용되기도 함
      • 이는 외장함수라 찾아볼것을 권장
scope : 변수의 범위

 

  • 기본 
    • 함수 내부에서 정의된 변수는 지역(로컬)변수라고 함
    • 절차적 코드에서 맨 앞칸에 정의된 변수 -> 전역(글로벌)변수
  • 종류
    • 전역변수 : global
      • 코드 전방위로 사용 가능
    • 지역변수 : local
      • 함수 내에서만 의미를 가짐
      • 함수 밖에서는 존재 / 사용 x
    • 넌지역변수 : nonlocal
      • 함수 내 함수가 존재하는 구조속에서 사용됨
score  = 100

def test() :
  print(score)

test()
print( '=>' , score)

출력값
100
=> 100

맨 앞에서 정해진 변수 score가 함수 내에서도 대입되는것을 알 수 있따

score = 100
def test() : 
  score = 0
  score += 1
  print(score)
test()
print( '->' , score)

이의 출력값은 어떻게 될까?

답은

1
-> 100

이는 함수 내에서 정의한 score는 함수 밖에서는 작용하지 않기 때문이다.
실제로 이렇게 쓰는 경우는 없지만 지역변수와 전역변수를 구분하기 위해서 만든 코드다

만약 score 변수를 함수 내에서 수정하고싶으면?
global을 사용하면 된다.

score = 100
def test():
  global score <- 여기서 이 score가 전역변수라고 명시 해주는것이다!
  score += 1
  print(score)
test()
print ('->' ,score)

출력값은

101
-> 101

전역변수를 함수 내에서 조작하여 밖에서도 변경된 값으로 나온것이다. 하지만 실제로 이럴 일은 거의 없다고 한다.

 

 

  • 애너테이션
    • 특징
      • 변수,함수,클래스 등 타입 가이드 문법
      • 타입 주석이라고 생각하면 된다
      • 애너테이션을 적용하면 무조건 지켜야 하는가? -> x 
      • 대상에 대한 주석같은 설명이 목적이다
    • 목적
      • 프로젝트 결과물 -> 애너테이션 적용 -> 깃허브 공개 , 배포
      • 코드의 퀄리티 상승되는 효과
      • 코드 관리 차원
변수 애너테이션
score = int = 100
name : str = 'python'

score, name
(100, '파이썬)

이때 타입에 대한 강제성은 없다.

score = 'python'
score
'python'
기본적으로 가능한 타입은 모두 가능하다, 다만 보기 좋게 정리한다는 느낌?
함수 애너테이션
기본형
def test_add ( x , y ):
  return x + y
test_add (1, 2) , test_add(1.1 , 2.0) , test_add ('hi', 'hello')
3, 3.1 , 'hihello'

애너테이션 반영할 시

def test_add2 ( x:int , y:int ) -> int:
  return x + y
test_add2 (1, 2 ) 
3

코딩에서 본 화면이다, 문제 없이 돌아가는걸 확인할 수 있다.
가이드를 통해서 int만 넣으라고 명시하였으니 
test_add2 ( 1, 'hi' ) 같은 시도를 방지할 수 있다.

 

모듈화_모듈 가져오기
  • 개요 
    • 파이썬 프로그램 구성
      • 모듈 <-> ipynb(노트북 파일, 분석 | 학습용)
        • .py
        • 파이썬 파일
      • # 실행
      • python .py
      • 패키지
        • 디렉토리(폴더)
        • 디렉토리 내부에는 여러개의 .py 또 다른 패키지 존재
        • 패키지는 같은 목적을 가진 모듈등이 모여있는 구조
      • 리소스 
        • 파일 ( 환경 변수, 이미지 미디어파일,...)
  • 모듈화 / 패키지
    • 팀 작업 -> 작업 자체가 분업 (각자 산출물이 존재)
      • 작업 공유 ( 다른 사람이 만든 모듈을 내가 사용해야 하는 상황)
      • 이를 위해 작성된 코드는 모듈화 되어야 함
  • 연습 구조 

  • 파일 구성
    • a > __init__.py
    • PI = 3.14
  • a > b > __init__,py
    • PI = 3.144
  • a > b > mod.py
    • # mod.py
    • # 변수 ( 상수 용도임)
    • PI3 = 3.1456789
  • # 함수
    • def add ( x , y )
    •   return x + y
  • 클래스
    • class A:pass
  • 모듈 가져오기 
    • 1번 유형
      • from ~ import ~
      • - from 패키지 . 패키지 . 패키지 . .....모듈 import 변수 | 함수 | 클래스 | *(와일드카드 -> 모든것이라는 뜻)
      • - from 패키지 . 패키지 . 패키지 . .....패키지 import 변수 | 함수 | 클래스 | *(와일드카드 -> 모든것이라는 뜻)
      • - from 모듈 | 패키지 import 변수 | 함수 | 클래스 | *(와일드카드 -> 모든것이라는 뜻)
      • 경로법은 반드시 프로그램이 시작되는 엔트리포인트 파일을 기준으로 절대경로로 계산
  • 2번 유형
    • import ~
    • - import 패키지 . 패키지 . 패키지 ....모듈
    • - import 패키지 . 패키지 . 패키지 ....패키지
    • - import 모듈 | 패키지
    • 공통 (통상 별칭을 자주 사용함)
      • import ...... as 별칭
1번 유형 

2번 유형

 

  • __name__
    • 사용 위치에 따라 2가지로 해석 (동적)
    • 사전에 정의된 파이썬의 전역변수
      • 유형 1
    • __name__ 을 사용한 모듈을 직접 실행한다면
    • - "__main__"
      • 유형 2
    • __name__이 기술된 모듈(xx.py) 를 다른 모듈에서 사용한다면
    • "패키지, 파일명"
    • ex -> a.test <- a = 패키지.test = 파일명

 

__name__

# 이게 개념이 조금 어렵다.

예를 들어 각자가 작업한 파이썬 파일이 있다. 이 때 자신의 컴퓨터가 메인으로 돌아가고 있을때에는 코딩이 작동하도록 하고 다른 사람의 컴퓨터에서는 파일이 작동하지 않게 하는 방법으로 보통 맨 위에 if __name__ == '__main__' 코드를 작성하여

메인이 아닌 프로그램에서는 작동하지 않도록 만드는것이다, 추후 많이 보일것으로 예상

기본적으로 본인이 메인인 컴퓨터에서는 아무 변수도 입력하지 않아도 __name__ 은 "__main__"으로 출력된다.

 

결론

모듈을 만드는 모든 사람들은 해당 모듈의 테스트코드등을 수행할 떄 반드시 아래 코드에서 진행 ( 단 테스트코드도 본 코드에 포함시키고 싶다면 x)

모든 서비스의 엔트리 포인트(진입로 , 시작 코드) 는  if __name__ == '__main__'  으로 표현한다

 

 

예외처리

파이썬 진영 처리 루틴

https://peps.python.org/pep-0463/

 

PEP 463 – Exception-catching expressions | peps.python.org

Just as PEP 308 introduced a means of value-based conditions in an expression, this system allows exception-based conditions to be used as part of an expression.

peps.python.org

개요 
  • 프로그램은 셧다운되면 안된다
  • 잠재된 오류상황에 대한 처리
    • 꼼꼼하게 테스트후 체크
      • 조건문이 아주 많이 사용됨
      • LBYL : Look Before You Leap
      • 에러가 나올만한 상황을 꼼곰하게 체크하여 코드를 구성
    • 진행 -> 오류 발생 -> 처리
      • 코드를 계속 진행 -> 수습은 나중에 (개발단계)
      • EAFP : Easier to Ask Forgiveness Than Permission
      • 허락보다 용서가 쉽다 ㅋㅋ
      • 파이썬은 이 방식을 권장함 -> 코드가 간결해짐 -> 회사 내의 문화를 참고
    • 그래서 예외처리가 필요함
      • 오류를 책임지고 잡아서 처리
        • try ~ except ~ else ~ finally ~ 
        • try ~ except ~  finally ~ 
        • try ~ except ~ else ~
        • try ~ except ~
      • 오류 던지기
        • 한 곳에서 오류를 일괄처리한다
        • raise ~
  • 문법
    • 공식 명칭 예외 처리 문
      • try :
        • 예외상황이 나올만한 (의심스런) 코드
        • I/O에서 보통 제일 많이 나옴
      • except 오류객체명1:
        • 오류 처리 (로그기록 , 등등)
      • except 오류객체명2:
        • 오류 처리 (로그기록 , 등등)
    • ............
      • [else:] 생략 가능
        • 오류가 없으면 진입함
        • 이런 상황을 알고싶다면 사용
      • [finally:] 생략 가능함
        • 뒷정리 코드
        • 오류가 발생 / 정상 관계없이 진입
      • 오류 객체
        • 최상위 객체 (모든 오류의 근본, 루트) -> Exception 으로 보통 많이 표현

 

예외 처리문의 예시

EAFP : 허락보다 용서가 쉽다

 

내 삶의 모토로 잡고 살아야