컴퓨터의 기본저장단위 : 바이트(Byte) = 8bit
* 따라서 1Byte에는 1bit는 0,1 두가지 값을 포함하므로 총 2^8(=256)개의 값 저장 가능
* 문자인코딩(Encording) : 문자나 기호의 집합을 컴퓨터에 저장하거나, 통신목적으로 사용하는 경우 부호로 변환
아스키 (ASCII)
- 미국에서 정의한 부호체계의 표준
- 아스키코드는 8비트를 모두 사용하는 것이 아니라 7bit(128개)의 값만 사용
- 나머지 1비트는 통신에러 검출을위해 사용하기 때문이다 = Parity Bit
- 이는 '영문 키보드'로 입력할 수 있는 모든 가능성을 담았지만, 다른 언어를 표현하기에는 부족
- 따라서 8bit를 모두 사용한 ANSI코드 출현
- 하지만 전 세계 문자를 정의하기엔 부족하여 등장한 것이 Unicode다.
유니코드 (Unicode)
- 용량을 2byte로 확장한 유니코드가 등장 - 즉, 2^16(=65536)개 저장 가능
- 버전에 따라 확장(저장크기증가)
- 국제적으로 전세계 언어를 모두 표시할 수 있는 표준코드
- 유니코드(Unicode)는 전 세계의 모든 문자를 표현하기 위한 표준 인코딩 체계
- 유니코드 프로그램 : 언어, 문자, 특수기호 등의 표준화
- 우리나라는 EUC-KR사용
UTF-8
- UTF-8은 유니코드를 인코딩(encoding)하는 방식, 전 세계에서 사용하는 약속
- 문자열을 UTF-8로 인코딩(암호화) : .encode("utf-8")
- 문자열을 UTF-8로 디코딩(암호화 해제) : .decode("utf-8")
유니코드는 국제표준 문자표이고 UTF-8은 인코딩 방식이다.
<유니코드 프로그램>
### 문자열 결합하기
### 문자열 결합하기
string1 = "파이썬(python)"
string2 = " 재미있어요"
string3 = "!!!"
word = string1 + string2 + string3
print(word)
결과
파이썬(python) 재미있어요!!!
### 문자열을 UTF-8로 인코딩
text = "안녕하세요"
encode_text = text.encode("utf-8")
encode_text
결과
b'\xec\x95\x88\xeb\x85\x95\xed\x95\x98\xec\x84\xb8\xec\x9a\x94'
### 문자열을 UTF-8로 디코딩하기
decode_text = encode_text.decode("utf-8")
decode_text
결과
'안녕하세요'
### "안녕하세요" 문자열을 for문을 이용해서 문자 각각 출력해주세요
# -인덱스 번호를 이용하는 방식으로 해주세요.
### for문 - 값을 이용해서 추출하는 방식
for v in decode_text:
print(v)
### for문 - 인덱스 번호를 이용해서 추출하는 방식
for i in range(0, len(decode_text), 1):
print(decode_text[i])
결과
안
녕
하
세
요
안
녕
하
세
요
### 눈 모양 유니코드 만들기 ( \u2603 )
char = "\u2603"
print(char)
# for문을 이용하지 말고, 눈사람 5개 출력해주세요
print(char*5)
결과
☃
☃☃☃☃☃
### 십진수 숫자값을 문자로 변환하기( chr() )
num = 65
print(num, chr(num))
결과
65 A
###문자열에서 특정 문자의 위치 찾기( index(), find() )
string = "안녕하세요!!!"
# "하"라는 문자의 위치(인덱스) 찾아주세요...
ha = string.find("하")
print(ha)
print(string.index("하"))
결과
2
2
### 문자 치환하기 ( replace() )
string = "python 기초 문법"
# "python" 영문 문자열을 찾아서 "파이썬" 한글명으로 수정하기
result = string.replace("python", "파이썬")
print(result)
결과
파이썬 기초 문법
클로저 (Closure)
- 함수 안에 함수를 만들어서 사용하는 방식
- 함수 안에 있는 함수는 바깥쪽 함수에서 참조해서 사용하는 방식으로 접근.
- 함수 안에 함수는 사용이 끝나면 메모리에서 해제되기 때문에 유용하게 사용하면 좋다.
- 함수는 호출이 되어야 실행된다.
- inner함수는 사용되고 나면 소멸된다. outer함수는 남아있음.(종료전까지)
- 따라서, 많은 데이터양을 처리할때 사용!!!
< 클로저 프로그램 >
### 클로저 함수 정의하기
def outer_function(x):
### 내부 함수 정의 : 실제 실행되는 함수
def inner_function(y):
s = x + y
return s
return inner_function
### 클로저 함수 호출하기
closure_exe = outer_function(10)
print(closure_exe)
# - clsure_exe는 inner_function 자체를 리턴받는 함수를 의미함
결과
<function outer_function.<locals>.inner_function at 0x000001FF70BCF060>
해석
'0x000001FF70BCF060' = inner_function주소값은 <locals>에 들어있어
clsure_exe는 inner_function 자체를 리턴받는 함수를 의미
### 내부 함수 호출하기
result1 = closure_exe(5)
print(result1)
결과
15
총 메모리 공간은 2개 생겼을 것!! ( outer_function , inner_function )
< closure 함수 실행 순서 알아보기>
def outer_function(x):
print(f" #1 : x = {x}")
### 내부 함수 정의 : 실제 실행되는 함수
def inner_function(y):
print(f" #2 : y = {y}")
s = x + y
print(f" #3 : s = {s}")
return s
print(" #4 --------")
return inner_function
closure_exe = outer_function(10)
print(closure_exe)
결과
#1 : x = 10
#4 --------
<function outer_function.<locals>.inner_function at 0x000001FF6FF81E40>
result1 = closure_exe(5)
print(result1)
결과
#2 : y = 5
#3 : s = 15
15
### 클로저를 이용해서 누적합 계산하기
# - 사용함수명 : outer_function2(), inner_function2(num)
# - 사용변수 : total(누적된 값을 저장할 변수)은 바깥함수에 둬야함(why? 내부함수는 실행 끝나면 소멸되므로)
# - nonlocal : 클로저 구조에서는 상위 변수를 내부 함수에서 사용못함.
따라서, nonlocal을 지정해서 정의하면 외부 영역의 변수 사용가능.
def outer_function2():
total = 0
def inner_function2(num):
nonlocal total
total += num
return total
return inner_function2
closure_exe2 = outer_function2()
print(closure_exe2)
결과
<function outer_function2.<locals>.inner_function2 at 0x000001FF700D3CE0>
result2 = closure_exe2(5)
print(result2)
결과
5
closure_exe2(10)
결과
15
<누적합 실행 순서 확인하기>
def outer_function2():
total = 0
print(f" #1 : total = {total}")
def inner_function2(num):
nonlocal total
print(f" #2 : total = {total} / num = {num}")
total += num
print(f" #3 : total = {total} / num = {num}")
return total
print(" #4 -------------inner_function2 주소값만 가져옴 ")
return inner_function2
closure_exe2 = outer_function2()
print(closure_exe2)
결과
#1 : total = 0
#4 -------------inner_function2 주소값만 가져옴
<function outer_function2.<locals>.inner_function2 at 0x000001FF701EEF20>
result2 = closure_exe2(5)
print(result2)
결과
#2 : total = 0 / num = 5
#3 : total = 5 / num = 5
5
closure_exe2(10)
결과
#2 : total = 5 / num = 10
#3 : total = 15 / num = 10
15
<조건부 클로저 함수 프로그래밍>
def outer_function3(condition):
def true_case():
return "true_case 함수가 호출되었습니다."
def false_case():
return "false_case 함수가 호출되었습니다."
### condition의 값이 True이면 true_case함수 정의
# False이면 false_case함수 정의
rs = true_case if condition else false_case
return rs
### 상위 함수 호출하기
rs_function = outer_function3(True)
print(rs_function)
rs_function = outer_function3(False)
print(rs_function)
결과
<function outer_function3.<locals>.true_case at 0x000001FF71A454E0>
<function outer_function3.<locals>.false_case at 0x000001FF71A471A0>
rs_msg = rs_function()
print(rs_msg)
결과
false_case 함수가 호출되었습니다.
데코레이터 (Decorator)
- 함수의 재사용성을 확장한 개념의 방법
- 데코레이터 사용하는 이유 : 은폐,엄폐하려고 + 많은양의 데이터를 처리할 때
- java의 오버로드(??), 오버라이드(함수 재사용)
- 오버로드(Overload): 같은 이름의 메서드가 매개변수의 타입, 개수, 또는 순서 등에서 다르게 정의
- 오버라이드(Override): 상속 관계에서 부모 클래스에 정의된 메서드를 자식 클래스에서 같은 시그니처로 재정의
- *args (가변 위치 인자): 값 인자 여러개
- *args는 함수를 정의할 때 사용되며, 함수에 임의의 개수의 위치 인자를 전달할 수 있도록 한다.
- *args는 관례적으로 사용되며, * 다음의 변수가 시퀀스 형태의 인자들을 모두 받음을 나타낸다.
- **kwargs (가변 키워드 인자): 딕셔너리,리스트 인자 여러개
- **kwargs는 함수를 정의할 때 사용되며, 함수에 임의의 개수의 키워드 인자를 전달할 수 있도록 한다.
- **kwargs 역시 관례적으로 사용되며, 이름은 중요하지 않습니다. ** 다음의 변수가 딕셔너리 형태의 키워드 인자들을 모두 받음을 나타낸다.
<함수 실행 시간 확인하는 데코레이터 프로그램 작성>
● 데코레이터 함수 정의하기
- func : 실제 처리할 함수 받아오는 매개변수
import time
### 데코레이터 함수 정의하기
# - func : 실제 처리할 함수 받아오는 매개변수(무조건??)
def timer_decorator(func):
### 실제 실행될 함수 정의:(함수 이름은 자유롭게)
print(f"#1 : func = {func}")
#데코레이터 함수가 리턴한 wrapper 함수는 exe_function이 된다.(재정의)
# - func로 받은 함수를 아래 함수로 재정의하게 됨
def wrapper(*args, **kwargs):
#args : argument(* : 변수)
#kwargs : keyword argument (** : 문자열관련 리스트, 딕셔너리..)
# - 시작시간
start_time = time.time()
print(f"#2 : 시작시간 = {start_time}")
### 실제 처리할 함수 : func
rs = func(*args, **kwargs)
print(f"#3 : rs = {rs}")
# - 종료시간
end_time = time.time()
print(f"#4 : 종료시간 = {end_time}")
return rs
print("#5----------------------")
return wrapper
● 데코레이터 호출 및 처리할 함수 정의하기
- 데코레이터 호출은 '@'을 사용함
- 데코레이터 함수 호출 시 밑에 정의된 함수(exe_function)가 매개변수로 자동으로 전달됨
- func는 exe_function함수의 주소값을 가짐
- 데코레이터 함수가 리턴한 wrapper 함수는 exe_function이 된다.
- time.sleep() : 데코레이터가 처리되는 시간을 벌어주기 위해서 쓰는 함수( 몇 초간 대기)
# - (재정의 되는 시점)
@timer_decorator
def exe_function():
print("실제 처리할 함수")
### 2초간 대기 : 데코레이터가 처리되는 시간을 벌어주기 위해서 ( sleep() )
time.sleep(2)
결과
#1 : func = <function exe_function at 0x00000292554EB9C0>
#5----------------------
● 실제 처리하기
exe_function()
결과
#2 : 시작시간 = 1699930632.5293994
실제 처리할 함수
#3 : rs = None
#4 : 종료시간 = 1699930634.5300581
설명
- rs = None인 이유 : exe_function()에 return값을 설정 안했으므로 print 값들만 출력
- exe_function함수의 주소값은 wrapper의 주소값으로 바뀜
<로그 데코레이터>
def log_decorator(func):
print(f"#1 : func = {func}")
def wrapper(*args, **kwargs):
print(f"Logo : {func.__name__}함수 호출됨")
rs = func(*args, **kwargs)
print(f"Logo : {func.__name__}함수 종료됨")
return rs
print("#2 --------------------")
return wrapper
● 데코레이터 호출 및 처리 함수 정의
@log_decorator
def another_function():
print("여긴 어디? 넌 누구?")
결과
#1 : func = <function another_function at 0x00000292560C3880>
#2 --------------------
● 처리 함수 호출
another_function()
결과
Logo : another_function함수 호출됨
여긴 어디? 넌 누구?
Logo : another_function함수 종료됨
<데코레이터 내부함수에서 처리된 결과를 받아보기>
def check_permission(param_id):
print(f"#1 : param_id = {param_id}")
def decorator(func):
print(f"#2 : func = {func}")
def wrapper(*args, **kwargs):
check_id = "admin"
print(f"#3 : check_id = {check_id}")
if check_id == param_id:
# *args, **kwargs는 리스트형식으로만 넣을 수 있음, 값1개면 args/ 값여러개면 kwargs
args = ["인증성공"]
print(f"#4 : args = {args}")
return func(*args, **kwargs)
else:
print(f"#5 : raise명령으로 강제 오류 발생 시킴--------")
raise PermissionError("접근 불가!!")
print("#6 --------------- ")
return wrapper
print("#7 --------------- ")
return decorator
● 데코레이터 호출 및 처리함수 정의
### 데코레이터 호출 및 처리함수 정의
@check_permission(param_id = "admin")
def admin_function(rs_msg):
print(f"인증 결과 : {rs_msg}")
결과
#1 : param_id = admin
#7 ---------------
#2 : func = <function admin_function at 0x00000292554EAA20>
#6 ---------------
● 처리 함수 호출
### 처리함수 호출
admin_function()
결과
#3 : check_id = admin
#4 : args = ['인증성공']
인증 결과 : 인증성공
<영문 소문자 2개를 매개변수로 받아서, 대문자로 변환하는 데코레이터 프로그램>
Q . 함수이름 자유롭게..생성
- 데코레이터 함수 생성하셔서 대문자로 출력까지...
● 방식1
def decorator1(func):
print("#1")
def wrapper(*args, **kwargs):
print("#2")
rs = func(*args, **kwargs)
print("#3")
return rs
print("#4")
return wrapper
@decorator1
def change_upper(str1, str2):
str1 = str1.upper()
str2 = str2.upper()
print("#5")
return str1, str2
결과
#1
#4
change_upper('apple', 'banana')
결과
('APPLE', 'BANANA')
※ 여기서 wrapper의 매개변수인 *args와 **kwargs를 각각 지워보고 실행해보니 *args는 실행이 되는데 **kwargs로 하면 오류가 발생했다. *kwargs는 딕셔너리 형태의 매개변수만 가능한 것 같다.
※ 위에 순서코드를 보면 알다시피 우리가 설정한 데코레이터 함수 chage_upper()는 wrapper()함수의 func위치에 들어가는 것 같다.
● 방식2
def decorator_upper(func):
### 인자로 넘어온 2개의 소문자는 args 매개변수가 받게됨
def wrapper(*args, **kwargs):
### 인자로 넘겨받은 개의 소문자를 대문자로 처리하는 영역
args = [arg.upper() for arg in args]
### 대문자로 변환된 값 2개를 args에 리스트 타입으로 담아서 넘기면 됨
return func(*args, **kwargs)
return wrapper
###데코레이터 호출 및 처리 함수 정의
@decorator_upper
def getUpper(param1, param2):
print(f"대문자로 변환된 {param1} / {param2}")
###처리하는 함수 호출 : 소문자 2개를 인자로 넘겨주기
getUpper("abcd","efgh")
결과
대문자로 변환된 ABCD / EFGH
※ 메모리 구조
실행 전 | 실행 후 |
decorator_upper공간(주소O) getUpper 공간 (주소O) wrapper 공간 (주소O) func 공간 → getUpper주소값 바라봄 |
decorator_upper공간(주소O) getUpper → wrapper 주소값 바라봄 wrapper 공간 (주소O) func 공간 (주소O = 실행 전의 getUper주소를 유지) |
<메모리 구조>
str = "안녕"
// str : 변수명 // = : 대입연산자(할당연산자) // "안녕" : 값
strList = [1, 2, 3]
def exe_func():
str = "안녕"
class A:
def __init__(sefl):
self.str = "안녕"
def str_msg(self):
print("m")
물리적 구조 | |
이름 영역 | 값 영역 |
str의 주소 | '안녕'값의 주소 |
strList의 주소 | 4개 주소(전체 영역 주소 ,'1'의주소, '2'의 주소, '3'의 주소) |
exe_func함수 주소 | 함수영역 주소 |
>> str주소 | '안녕' 값의 주소 |
wrapper함수 주소 | 함수영역 주소 |
>> 안의 값들 | 값의 주소 |
class A의 주소 | 클래스 A의 영역 주소 |
>> str 주소 | "안녕" 값의 주소 |
>> str_msg 주소 | 함수영역 주소 |
* 안녕이라는 값의 주소값이 str의 주소에 대입연산자(=)를 통해 넘어가게 됨.
* 데코레이션 방식 : 주소값을 바꿔치기하는 방식(너도 이곳의 주소를 봐)
ex) exe_func함수를 데코레이션 해서 wrapper함수의 주소값을 보게 한다.
파이썬에서 반드시 알아야하는것
리스트(튜플), 딕셔너리, if문, for문 꼭 따로 공부해보자!!
'Back-End > Python' 카테고리의 다른 글
[Python] 파이썬의 기초 - 매개변수, 기본값(default) (2) | 2023.11.14 |
---|---|
파이썬 실습2 - 도서 입고/대출/반납 관리를 위한 키오스크 만들기 (데코레이터) (1) | 2023.11.14 |
[Python] 파이썬 실습 - 도서 입고/대출/반납 관리를 위한 키오스크 만들기 (2) | 2023.11.13 |
[Python] 파이썬 환경 설정 - anaconda3, jupyter notebook (2) | 2023.11.13 |
[Python] 인터프리터와 컴파일러 (3) | 2023.11.13 |