메서드에 리턴된 값이 순차적으로 해소가 되는 방식을 뜻한다
'Hello World'.replace('Hello', 'hi').lower()
# 그 메서드에 리턴된 값이 순차적으로 해소가 되는 방식
# 'hello world'.a().b().c().d()
# 'Hello World'.split().lower() # error
'Hello World'.split()[0].lower()
첫번째 점부터 마지막점까지 순차적으로 실행이 된다.
문자열을 리스트로 형변환하면 어떻게 될까?
list('hello world')
# 출력
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
class Calculator:
def __init__(self, value):
self.value = value
def add(self, other):
self.value += other
return self
def subtract(self, other):
self.value -= other
return self
def multiply(self, other):
self.value *= other
return self
def get_value(self):
return self.value
calc = Calculator(1)
result = calc.add(2).subtract(1).multiply(3).get_value()
print(result) # 결과: 6
multiply까지는 calc를 반환하지만 get_value는 value를 반환하므로 get_value 이후에는 문자열 메서드를 사용하지 못한다. 따라서 형변환을 진행하는 등의 조치가 필요하다.
int, float, complex 자료형에 모두 있는 것은?
a = 3
b = 3.5
c = 3j + 1 # i를 많이 사용하기에 j를 대신 사용함
dir(a)
dir(b)
dir(c)
# 'imag' # 허수부
# 'real' # 실수부
dir()로 각 변수를 찍어보면, a, b, c 세 변수 모두 실수부와 허수부를 메서드로 갖고 있다. 이는 복소수와의 연산을 위한 것 같다.
일급 함수는 함수를 값(변수)로 취급하는 것
def greet(name):
return f'Hello, {name}'
say_hello = greet
print(say_hello("World")) # 출력: Hello, World
위의 예시처럼 함수는 변수로 사용할 수 있다.
변수가 너무 길때, 줄여서 사용하기도
l = [10, 20, 30]
# l.append(100)
add = l.append
add(10)
add(20)
# 이렇게 사용할 일은 거의 없다.
# 변수가 너무 길 때, 오타가 많이 생기는 변수일 때,
# 메서드 명도 길때 줄여서 사용하기도 한다!
l # [10, 20, 30, 10, 20]
팀프로젝트에서는 사용하면 안되겠지만 개인 프로젝트에서는 간단히 줄여서 사용하기도 한다고 한다.
def add(x, y):
return x + y
def subtract(x, y):
return x - y
funcs = [add, subtract]
print(funcs[0](2,3)) # 출력 5
class Operator:
def add(self, x, y):
return x + y
def sub(self, x, y):
return x - y
def mul(self, x, y):
return x * y
def div(self, x, y):
return x / y
def _and(self, x, y):
pass
def _or(self, x, y):
pass
op = Operator()
logical_op = {
'add': op.add,
'sub': op.sub,
'mul': op.mul,
'div': op.div,
}
arithmetic_op = {
'_and': op._and,
'_or': op._or,
}
print(logical_op['add'](2, 3)) # 출력: 5 마치 op.add(2, 3)인 것 처럼 사용할 수 있다.
print(op.add(2, 3)) # 출력: 5. 위와 동일
for _, f in logical_op.items():
print(f(2, 3)) # 4칙연산 모두 계산
위의 함수와 아래 함수는 같은 역할을 한다.
def add(a, b):
return a + b
add(2, 3)
정리하면 인스턴스나 클래스에 직접 접근하지 않고도 내가 만든 변수로 관리 할 수 있다는 장점이 있다.
def add(a, b):
return a + b
def say_hello(name):
return f'Hello, {name}'
def greet(func, name):
return func(name)
print(greet(say_hello, 'World')) # 출력: Hello, World
위와 같이 작성할수도 있고, 아래와 같이 사용할 수도 있다.
# 별표 1개 => 데코레이터를 이해하기 위해 중요한 개념
# 함수를 아규먼트로 받거나 반환할 수 있다 => 고차함수
def add(a, b):
return a + b
def say_hello(name):
return f'Hello, {name}'
def greet(func):
return func
print(greet(say_hello)('World')) # 출력: Hello, World
다른 예시를 보자.
def create_adder(x):
def adder(y):
return x + y
return adder
add_5 = create_adder(5)
print(add_5(10)) # 출력: 15
위 함수에서 x=5라는 값이 들어가는데 분명이 함수가 끝났음에도 x가 살아서 add_5(10)으로 y값을 받아 15를 출력하는 것을 볼 수 있다.
이는 변수가 하나라도 참조중이면 사라지지 않음을 알 수 있다. 이를 클로져라고 한다.
변수를 변경 불가능하게 감추기 위한 코딩 기법이 존재한다
def create_sq(x):
def sq(y):
return x ** y
return sq
제곱2 = create_sq(2) # x를 변경 불가능하게 감추기 위한 코딩 기법
제곱3 = create_sq(3)
제곱4 = create_sq(4)
제곱2(2), 제곱2(3), 제곱2(4)
제곱3(2), 제곱3(3), 제곱3(4)
제곱4(2), 제곱4(3), 제곱4(4)
위의 코드를 보면 x를 따로 집어넣지 않고 뒤에서 활용하고 있다.
def 숫자출력(count):
if count > 100:
return
print(count)
return 숫자출력(count+1) #값을 1부터 반복횟수 까지의 값을 출력
숫자출력(1)
재귀함수로 구현 가능한 것은 대부분 for문으로 쉽게 구현이 가능하다.
# 권장
for i in range(1, 101):
print(i)
재귀함수는 알고리즘 문제(분할 정복, 다이나믹 프로그래밍)에서 쓰인다고 한다.
# f(5) => 5 * 4 * 3 * 2 * 1 == 120
def f(n):
if n <= 1:
return n
return n * f(n-1)
f(5) # 120
위의 코드보단 아래의 코드를 권장한다.
# 권장
result = 1
for i in range(1, 6):
result *= i
result
몇가지 예시를 더 보고 마무리 하자.
def f(n):
if n <= 1:
return n
return n * f(n-1)
# f(5) 5 * f(4) == 5 * 24 => 120
# f(4) 4 * f(3) == 4 * 6
# f(3) 3 * f(2) == 3 * 2
# f(2) 2 * f(1) == 2 * 1
# f(1) 1
s = ''
for i in 'hello':
s = i + s
s # 'olleh'
# s = 'h' + ''
# s = 'e' + 'h'
# s = 'l' + 'eh'
# s = 'l' + 'leh'
# s = 'o' + 'lleh'
def f(s):
if len(s) <= 1:
return s
return f(s[1:]) + s[0]
f('hello')
# f('hello') f('ello') + 'h' == 'olleh'
# f('ello') f('llo') + 'e' == 'olle'
# f('llo') f('lo') + 'l' == 'oll'
# f('lo') f('o') + 'l' == 'ol'
# f('o') 'o'
# 첫번째 방법
def apply_function(lst, func):
return [func(i) for i in lst]
# 예제 사용
result = apply_function([1, 2, 3, 4], lambda x: x * 2)
print(result) # [2, 4, 6, 8]이 출력되어야 함
# 두번째 방법(권장)
def apply_function(lst, func):
return list(map(func, lst))
# 예제 사용
result = apply_function([1, 2, 3, 4], lambda x: x * 2)
print(result) # [2, 4, 6, 8]이 출력되어야 함
def multiply_by_n(n):
return lambda x: x * n
# 예제 사용
multiplier = multiply_by_n(5)
print(multiplier(3)) # 15가 출력되어야 함
어제 연습문제를 풀면서 어렵다라고 생각했는데 오늘 풀이를 보니까 다들 똑같이 생각한 것 같다 ㅋㅋㅋ. 그건 그렇고.. 오늘은 파이썬 심화과정으로 메서드 채이닝, 일급함수와 고차함수, 재귀함수에 대해 배워봤다. 메서드 채이닝은 이전에도 몇번씩 해서 괜찮았던 것 같고 일급함수와 고차함수라는 단어를 처음 들었는데 중요하다고 하셨던 것 치고는 생각보다 어렵진 않았어서 한번 싹 훑고 지나갔다. 재귀함수는 예전에 몇번 보긴 했는데 그때도 그렇지만 지금도 조금 헷갈리는 부분이 있는 것 같다. 이쯤되면 일부러 그렇게 만든걸수도?? for문으로 쓰는게 익숙해지기 전까지 좋다고 하시니까 그렇게 하도록 노력하겠다.
오늘 부로 책 집필 프로젝트(코팅 테스트)를 시작하게 되었는데 어차피 해야할 공부를 다같이 한다는게 좋은 것 같다. 혼자하면 중간에 어렵다고 그런 경우도 있으니까. 문제는 pyalgo 100제로 시작을 할 것 같고.. 일주일에 2번가량 모여서 설명해주고 책 페이지 채우고 이런식으로 진행할 것이다. 뭔가 혼자하면 안할 것 같아서 스터디고 뭐고 신청을 했는데 모두 포기하지 말고 끝까지 가서 좋은 결과가 있으면 좋겠다.