21.1.24
<코딩도장 복습 통한 새로 이해한 내용 정리 : Unit : 32~33>
- 람다 표현식 :
"함수를 다른 함수의 인수로 넣을 때 주로 사용"
-> 자바스크립트에서 함수는 객체이기 때문에 다른 함수의 인자가 될 수 있다는 이야길 들은 것 같다. 그 원리를 이용한 객체지향적 개념이 아닐까 싶다.
def plus_ten(x):
return x+10
이를 람다 표현식으로 하면 다음과 같다
plus_ten = lambda x : x + 10
즉 "함수 이름 = lambda 매개변수 : 식"
따라서 람다 식 전체를 괄호 친 후 (인자) 를 넣으면 바로 실행되기도 한다. 단 이미 만들어진 람다의 식 안에 또 다른 매개변수가 들어갈 수는 없다.(따로 선언해야 함.)
-
단 코드에 길이가 너무 길어지겠다 싶으면 그냥 함수 선언을 하는 것이 더 좋을 때가 있다.
-
list처럼 시퀀스 객체를 인자로 받아야 하는 상황에서는 list(map...)을, 리턴 값이 어떤 필터링이 필요하다면 filter를 메서드로 사용한다.
-
reduce함수 : 반복 가능한 객체(시퀀스 객체)의 누적 값을 반환하는 함수로 내장함수가 아니어서 불러와야 함. 사용법 및 결과는 다음과 같음
>>> def f(x, y):
... return x + y
...
>>> a = [1, 2, 3, 4, 5]
>>> from functools import reduce
>>> reduce(f, a)
15
(람다)
>>> a = [1, 2, 3, 4, 5]
>>> from functools import reduce
>>> reduce(lambda x, y: x + y, a)
15
- 문자열 포메팅과 메서드를 이용한 연습문제32
files = ['font', '1.png', '10.jpg', '11.gif', '2.jpg', '3.png', 'table.xslx', 'spec.docx']
print(list(filter(lambda x : x.find('.jpg') != -1 or x.find('.png')!= -1, files)))
풀이 : 먼저 map을 사용할 경우 리스트로 만들어지기는 하지만 분류가 되지 않는다. 그러므로 filter를 사용한다.
다음 단순히 문자열 포멧팅을 사용할 경우 모두가 jpg, png로 바뀌는 알고리즘만 나온다. 따라서 문자열 메서드 중 find의 성질을 이용. 특정 값이 나오면 몇 번 째 인덱스인지 찾아주고 없으면 -1을 출력하는 성질을 반대로 이용. 생각이 안 나서 한참을 고민했다가 풀었다. 아마 푼지 좀 되어서 방식을 다시 까먹은 것 같다.
- 클로저
- 변수의 사용 범위 :
스크립트 전체에서 사용할 수 있는 변수 : 전역변수
그 범위 : 전역범위
x = 10 # 전역 변수
def foo():
print(x) # 전역 변수 출력
foo()
print(x) # 전역 변수 출력
반대로 특정 함수 혹은 특정 지역에서만 사용하는 변수를 지역변수. 그 범위를 지역범위라고 함.
x = 10 # foo의 지역 변수
print(x) # foo의 지역 변수 출력
foo()
print(x) # 에러. foo의 지역 변수는 출력할 수 없음
만일 전역 변수가 있는데 이를 '지역변수로만' 사용하고 싶다면?
global 선언 통해 지역변수 자리에서 전역변수를 선언하여 전체 사용.
x = 10 # 전역 변수
def foo():
global x # 전역 변수 x를 사용하겠다고 설정
x = 20 # x는 전역 변수
print(x) # 전역 변수 출력
foo()
print(x) # 전역 변수 출력
- 함수 안에서 함수를 만든다.
def print_hello():
hello = 'Hello, world!' # 함수 정의
def print_message():
print(hello) # 함수 정의
print_message() # 함수 호출
-----(지역변수 hello접근 범위)------
print_hello() # 함수 호출
다른 예시
def A():
x = 10 # A의 지역 변수 x
def B():
x = 20 # x에 20 할당
B()
print(x) # A의 지역 변수 x 출력
-------(지역변수 x = 10 접근 범위)-------
A()
10
A함수의 지역변수가 작용하는 범위라 10이 나옴.
만일 20이 나오게 하고 싶다면? -> nonlocal x
def A():
x = 10 # A의 지역 변수 x
def B():
nonlocal x # 현재 함수의 바깥쪽에 있는 지역 변수 사용
x = 20 # A의 지역 변수 x에 20 할당
B()
print(x) # A의 지역 변수 x 출력
A()
20 (바깥쪽 쓰는 것으로 변경)
하지만 실무에서 이렇게 쓰는 일 별로 없음. 변수는 이름 꼭 다르게 사용할 것을 추천.
이러한 것들을 상관 안 하고 global을 쓰면 무조건 전역변수를 쓸 수 있다.
x = 1
def A():
x = 10
def B():
x = 20
def C():
global x
x = x + 30
print(x)
C()
B()
A()
31
- 본격 클로저 알아보기
def calc():
a = 3
b = 5
def mul_add(x):
return a * x + b # 함수 바깥쪽에 있는 지역 변수 a, b를 사용하여 계산
return mul_add # mul_add 함수를 반환
c = calc()
print(c(1), c(2), c(3), c(4), c(5))
calc()는 호출되는 것으로 사실 함수가 끝났는데 c(1), c(2).. 처럼 지역 변수, 코드를 유지하고 있다가 호출 할 때 안에 가지고 있는 함수를 다시 사용하는 개념을 '클로저'라고 함.
클로저는 프로그램의 흐름(함수 형태 등)을 변수에(위의 c처럼) 저장하여 쓰고 싶을 때 쓸 수 있다. 클로저에 지역 변수는 바깥에서 직접 법근이 어렵고 데이터를 숨기고 싶을 때 주로 사용한다.
여기서 두 번째로 def 된 함수를 람다식으로도 표현할 수 있다고 한다.
(return lambda x: a * x + b) : 함수 안에 함수를 넣은 형태
클로저 : 변수라는 이름을 가진 환경을 유지했다 쓰는 함수
람다 : 이름이 없음.(변수 등을 지정하지 않는다는 뜻)
만일 지역변수에 변화를 주고 싶다면(이를테면 누적식을 만들어버리고 싶다.) nonlocal을 사용하면 된다.
def calc():
a = 3
b = 5
total = 0
def mul_add(x):
nonlocal total
total = total + a * x + b
print(total)
return mul_add
c = calc()
c(1)
c(2)
c(3)
개념 정리 후 드는 생각 :
한 6~7번은 보니까 쪼금은 알 것 같다. 먼저 지역변수와 전역변수의 차이, 지역 범위와 전역 범위의 차이부터 잘 익혀두자.
- 개념 응용 연습문제 32
def counter():
i = 0
def count():
nonlocal i
i += 1
return i
return count
c = counter()
for i in range(10):
print(c(), end=' ')
nonlocal로 counter의 변수 i를 가지고 온 뒤 counter가 호출 될 때마다 1 씩 느는 것이므로 +=1 처리를 해준다. 이후 이걸 그냥 리턴해주면 된다.(print처리 하니까 counter의 nonetype 값까지 같이 나와서 애먹었다.)
Author And Source
이 문제에 관하여(21.1.24), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sinichy7/21.1.24저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)