함수(function - oop method) oop 객체지향에서는 method라고 표현¶
- 코드 재사용
- 가독성 향상
- 유지보수 용이
- 디버깅 용이
- 모듈화(import utils)
def 함수이름([매개변수, 매개변수, .........]) :
실행할 코드
return 결과값(내장변수타입) # 반환이 필요없다면 생략 가능
In [27]:
print('working - ')
print('default parameter - ')
def greet(name='guest'):
'''사용자에게 인사하는 함수'''
return (f'hi ~, {name}')
working - default parameter -
In [31]:
print('caller - ')
result = greet()
print(result)
caller - hi ~, guest
In [21]:
def userAdd(a,b):
return a ** b
In [32]:
print('positional argument - ')
result = userAdd(3,2)
print('type - ', type(result))
print('result - ', result)
positional argument - type - <class 'int'> result - 9
In [33]:
print('keyword argument - ')
result = userAdd(b=3,a=2)
print('type - ', type(result))
print('result - ', result)
keyword argument - type - <class 'int'> result - 8
- 람다 함수(Lambda function) == 익명의 함수(anonymous)
- lambda 매개변수 : 실행문 (return 키워드 없이 결과값을 바로 반환)
- map, filter~
In [38]:
add = lambda x, y : x + y
print('type - ', type(add))
type - <class 'function'>
In [39]:
result = add(3, 5)
print('result - ', result)
result - 8
In [57]:
lst = [1,2,3,4,5,6,7,8]
print('case01 - ')
result = [data ** 2 for data in lst]
print(result)
print('case02 - ')
print('map - 열거형 타입(반복 가능한 요소에 대해서 특정 함수를 적용하고 그 결과를 map 객체로 반환)')
print('map(function, iterable)')
double = list(map(lambda data : data ** 2 , lst ))
print(double)
print()
print('case03 - ')
print('filter(function, iterable) ')
even = list(filter(lambda data : data % 2 == 0 , lst ))
print(even)
case01 - [1, 4, 9, 16, 25, 36, 49, 64] case02 - map - 열거형 타입(반복 가능한 요소에 대해서 특정 함수를 적용하고 그 결과를 map 객체로 반환) map(function, iterable) [1, 4, 9, 16, 25, 36, 49, 64] case03 - filter(function, iterable) [2, 4, 6, 8]
In [61]:
wordLst = ['pineApple', 'cherry', 'watermelon', 'banana', 'apple']
result = sorted(wordLst, key=lambda x : len(x))
print(result)
['apple', 'cherry', 'banana', 'pineApple', 'watermelon']
In [76]:
# 반환예시) [ 'www.skshielus.com', 'www.samsung.com' , etc .....]
def makeUrl(lst : list) -> list :
#return [f'www.{data}.com' for data in lst]
return list(map(lambda x: 'www.'+x+'.com', lst))
In [81]:
companyLst = ['skshieldus', 'samsung', 'lgcns', 'skcnc', '<script>alert(1)</script>']
urls = makeUrl(companyLst)
print(urls)
['www.skshieldus.com', 'www.samsung.com', 'www.lgcns.com', 'www.skcnc.com', 'www.<script>alert(1)</script>.com']
In [96]:
# 코드의 개선점
# 내부값이 문자열인지, 악성문자열 검증
# 웹 페이지에 출력하면 XSS 취약점 발생
# quote() : 공백, 특수문자 등을 안전하게 인코딩
from urllib.parse import quote
# def safemakeUrl(lst : list) -> list :
# return list(map(lambda x: 'www.'+quote(x)+'.com', lst))
# isinstance 입력받은 lst 타입이 list 타입인지
def safemakeUrl(lst : list) -> list :
if not isinstance(lst, list):
raise TypeError("입력은 리스트 타입으로 전달 부탁드립니다.")
if not all(isinstance(name, str) for name in lst) :
raise ValueError("요소의 타입은 문자열")
# 안전하게 URL 인코딩
return list(map(lambda x: 'www.'+quote(x)+'.com', lst))
In [98]:
companyLst = ['skshieldus', 'samsung', 'lgcns', 'skcnc', '<script>alert(1)</script>']
urls = safemakeUrl(companyLst)
print(urls)
['www.skshieldus.com', 'www.samsung.com', 'www.lgcns.com', 'www.skcnc.com', 'www.%3Cscript%3Ealert%281%29%3C/script%3E.com']
In [119]:
def myColor(name, color, isLike : bool) :
print(f'{name}님은 {color}색을 {'좋아' if isLike else '싫어'}합니다.')
In [120]:
# 출력예시) XXX님은 xxx색을 좋아(싫어)합니다.
myColor('섭섭님', 'red', False)
myColor('섭섭님', 'blue', True)
섭섭님님은 red색을 싫어합니다. 섭섭님님은 blue색을 좋아합니다.
- 변수의 스코프에 대한 이해(LEGB)
In [133]:
# 전역변수
globalVar = 10
def outer() :
# 외부 함수 변수
enclosingVar = 20
def inner() :
# 지역변수
localVar = 30
print('global - ', globalVar)
print('enclosingVar - ', enclosingVar)
print('localVar - ', localVar)
inner()
# error
# print(localVar)
In [134]:
outer()
print('globalVar - ', globalVar)
# error
# print(enclosingVar)
global - 10 enclosingVar - 20 localVar - 30 globalVar - 10
In [135]:
x = 10
def test() :
x = 20
In [136]:
test()
print('x - ', x)
x - 10
In [146]:
cnt = 0
def increment () :
global cnt
cnt += 1
In [147]:
increment()
increment()
increment()
print('cnt - ', cnt)
cnt - 3
In [156]:
def outer() :
outerVar = 10
def inner() :
nonlocal outerVar # nonlocal 외부 함수를 호출 가능하게 해줌
outerVar += 1
print('inner outerVar : ', outerVar)
inner()
print('outer outerVar : ', outerVar)
In [161]:
outer()
inner outerVar : 11 outer outerVar : 11
- 클로저(Closure)(중첩함수 - 함수내부에서 외부함수의 변수를 기억)
- 함수가 종료되어도 외부 변수를 기억하는 것이 핵심
- 상태유지(전역변수를 쓰지 않고도 함수 내부에서 상태 유지 가능)
- 함수 장식자(데코레이터) : 클로저 기반
In [171]:
def outer(name : str):
def inner():
return f'hi ~ , {name}'
return inner # 함수반환
In [175]:
msg = outer('jslim')
print('type - ', type(msg))
print('result - ', msg())
type - <class 'function'> result - hi ~ , jslim
In [179]:
# 전역변수를 사용하지 않고 상태를 유지하는 코드 개선
def counter():
count = 0
def increase():
nonlocal count
count += 1
return count
return increase
In [180]:
cnt = counter()
print(cnt())
print(cnt())
print(cnt())
print(cnt())
print(cnt())
1 2 3 4 5
- decorator(함수 장식자)
- 함수를 감싸서 기능(공통의 로직)을 추가시켜주는 것
- 현업에서 자주 사용되는데 : 로깅, 권한체크, 실행시간 측정, etc......
In [198]:
def commonChecking():
print('>>>>>>>>> permission check')
def commonLogging() :
print('>>>>>>>>> log......')
def decorator(checkingFunc, loggingFunc):
def logic():
checkingFunc()
print('업무로직')
loggingFunc()
return logic
In [199]:
innerLogic = decorator(commonChecking, commonLogging)
innerLogic()
>>>>>>>>> permission check 업무로직 >>>>>>>>> log......
In [213]:
def clo(num):
x = 10
def test():
nonlocal x
x = x + num
return x
return test
a = clo(1)
print(a())
print(a())
print(a())
11 12 13
In [20]:
print('실행시간 성능 로그 - ')
from time import time, sleep
def timer(func):
def wrapper(*args, **kwargs):
start = time()
result = func(*args, **kwargs)
elapsed = time() - start
if elapsed > 2 :
print(f'경고 : {func.__name__}, 실행시간 : {elapsed:.2f}초 초과되어서 알림')
return result
return wrapper
def timerFunc():
sleep(1)
return '성능확인'
실행시간 성능 로그 -
In [21]:
# 함수 장식자
@timer
def timerFunc():
sleep(1)
return '성능확인'
inner = timerFunc()
print(inner)
성능확인
In [22]:
def timerFunc():
sleep(1)
return '성능확인'
inner = timer(timerFunc)
print(inner())
성능확인
- 가변인자 함수 : 몇개의 매개변수가 전달될지 모르는 것
- *args : tuple
- **args : 키워드 인자로 dict
In [227]:
def variableLenArgs(*args : int) -> None :
print('type - ', type(args))
total = sum(args)
return total
In [230]:
result = variableLenArgs(1,2,3)
print(result)
result = variableLenArgs(1,2,3,4,5)
print(result)
result = variableLenArgs(1,2,3,4,5,6,7)
print(result)
type - <class 'tuple'> 6 type - <class 'tuple'> 15 type - <class 'tuple'> 28
In [250]:
def variableLenArgsDict(**args) :
print('type - ', type(args))
for key, value in args.items():
print(key,value)
In [251]:
variableLenArgsDict(name='jslim',age=30,region='seoul')
type - <class 'dict'> name jslim age 30 region seoul
In [269]:
def variableLenArgsMix(subject, *args, **kwargs):
print('subject - ', subject)
print('args - ', args)
print('kwargs - ', kwargs)
In [273]:
variableLenArgsMix('사용자 정보 ', '임섭순', '섭섭해', '쉴더스', a=1,b=2)
subject - 사용자 정보
args - ('임섭순', '섭섭해', '쉴더스')
kwargs - {'a': 1, 'b': 2}
In [313]:
# endpoint
# Quiz
# 아래와 같은 api 요청을 생성
# https://api.v1.example.com/search?q=secure&page=2
def makeApiRequest(endpoint, **params) :
query = "&".join([f"{k}={v}" for k, v in params.items()])
print(f'{endpoint}?{query}')
return (f'{endpoint}?{query}')
In [314]:
api = makeApiRequest('https://api.v1.example.com/search', q='secure', page=2)
print(api)
https://api.v1.example.com/search?q=secure&page=2 https://api.v1.example.com/search?q=secure&page=2
In [295]:
def makeApiRequest(endpoint, **params):
# params를 key=value 형태로 연결
query = "&".join([f"{k}={v}" for k, v in params.items()])
url = f"{endpoint}?{query}"
print(url)
return url
def makeApiRequest(endpoint, **params):
query = ""
for k, v in params.items():
if query == "":
query += f"{k}={v}"
else:
query += f"&{k}={v}"
url = endpoint + "?" + query
print(url)
return url
In [296]:
api = makeApiRequest('https://api.v1.example.com/search', q='secure', page=2)
print(api)
https://api.v1.example.com/search?q=secure&page=2 https://api.v1.example.com/search?q=secure&page=2
In [303]:
from urllib.parse import urlencode
params = {'q' : 'secure', 'page' : 2}
queryString = urlencode(params)
print(queryString)
q=secure&page=2
In [305]:
from urllib.parse import urlencode
def makeApiRequest(endpoint, **params) :
queryString = urlencode(params)
return endpoint+'?'+queryString
api = makeApiRequest('https://api.v1.example.com/search', q='secure', page=2)
print(api)
https://api.v1.example.com/search?q=secure&page=2
In [311]:
print('보안 - 코드 개선')
from urllib.parse import urlencode
def makeApiRequest(endpoint, **params) :
whiteLst = {'q', 'page', 'lang'}
safeParams = { k : v for k, v in params.items() if k in whiteLst}
queryString = urlencode(safeParams)
return endpoint+'?'+queryString
보안 - 코드 개선
In [312]:
api = makeApiRequest('https://api.v1.example.com/search', q='secure', page=2)
print(api)
https://api.v1.example.com/search?q=secure&page=2
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]: