Python Repl.it : #53 ~ #58 에서 다룬 개념들을 정리했다.!
확실히 text를 읽는것보단 실습이, 실습보단 개념을 정리해 나의 단어로 정리하는것이 이해하는데 가장 효과적인거같다! (내 기준!!ㅎㅅㅎ)
중첩 함수는 말 그대로 함수를 중첩해서 사용하는 것
이다. 즉, 함수 속에 또다른 함수
가 존하여 내부 함수의 값이 부모 함수의 값에 영향을 준다.
다음과 같은 예시가 있다.
def parent_function():
def child_function():
print("this is a child function")
child_function()
parent_function()
-> "this is a child function"
먼저 부모함수인 parent_function() 안에 내부함수인 chile_function()이 존재한다. 각각 함수의 기능은 다음과 같다.
때문에 부모함수의 기능을 호출하면 결론적으로 내부함수의 기능까지 수행되는 것이다.
크게 두가지가 있다.
여러개의 함수가 존재하는데 그 함수들 안에 모두 공통된 코드가 존재한다면? 매번 같은 코드를 입력하는 것은 비 효율적이고, 한눈에 같은 코드임을 파악하기가 어렵다! 때문에 반복되는 코드는 또 다른 함수로 정의하여 함수안에 함수로 입력하는 것이다.
사전적 의미로 폐쇄
를 뜻한다 즉, "무언갈 가둔다" 라는 것이다.
Python의 중첩함수에서 closure는 중첩 함수가 부모 함수의 변수나 정보를 가두어 사용하는 것
을 의미한다!!
그리고 나서 부모함수는 중첩 함수를 return 한다.
부모함수의 변수를 외부로부터 직접적인 접근은 격리 하면서, 동시에 중첩 함수를 통해 격리된 부모함수의 변수를 사용한 연산은 가능하게 한다.
이런 특성을 이용해 중첩함수를
" 어떤 정보를 기반으로 연산을 실행하고 싶지만 기반이 되는 정보는 접근을 제한하여 노출이 되거나 수정이 되지 못하게 하고 싶을 때 "
사용한다.
다음과 같은 코드가 있다고 가정한다.
def calculate_power_of_two(power):
return 2 ** power
calculate_power_of_two(7)
-> 128
수 2에 대해 특성 숫자(변수 power에 대입) 승을 구하는 함수이다. (출력예시 = 2의 7승 => 128)
만약 수 2 뿐만이 아니라 다양한 수에 대해서 위와 같은 계산을 진행하고 싶다면?? 새로운 숫자에 대한 함수를 만들면 된다!
def generate_power(base_number):
def nth_power(power):
return base_number ** power
return nth_power
calculate_power_of_two = generate_power(2)
calulate_power_of_two(7)
-> 128
사실 위의 예시로는 이해가 잘 안됐다. 문제의 개념을 직관적으로 파악하기 어려운 구조라고 생각한다;;;;,,, (내 기준)
다음에 나올 Decorator의 개념을 알면 더 쉽게 이해할수 있다!!
Decorator는 closure 개념을 이용해 사용하는 고급 기능이다.
표현은 @데코레이터명
으로 표현한다.
Decorator는 방금 말했듯이 closure 개념을 이용해 사용하는 고급 기능이다. 따라서
- (closure 처럼) 중첩함수를 리턴하는 함수이다.
- 특정 함수를 실행하기 전에 강제적으로 다른 함수가 먼저 실행된 후 실행되도록 하는 강제성을 제공하는 기능이다.
def welcome_decorator(hello):
def wrapper():
return hello() + "welcome to WECODE!"
return wrapper
@welcome_decorator
def greeting():
return "Hello, "
이거은 welcome_decorator
라는 데코레이터를 사용한 것이다. 이는 중첩함수인 wrapper
를 리턴하는 함수로, 그 함수가 실행되기 전에 강제적으로 greeting
함수가 먼저 실행되도록 한다.
각 함수의 리턴값을 살펴보면
- greeting 함수는"Hello, "를 return 하는 함수
- 중첩함수(wrapper함수)는 welcome_decorator의 변수로 들어온 값 뒤에 "welcome to WECODE!"를 리턴
- 최종적으로 welcome_decorator가 중첩함수의 값을 리턴
위의 예시에서 중첩함수가 리턴하는 hello()는 아래에 쓰인 welcome_decorator라는 데코레이터와 관련된 함수 greeting()의 return 값을 의미한다.
(hello는 임의의 단어를 기입한 것이다. 중첩함수에서 입력해주어야 하므로 공백으로 둘 수 없었다.)
Scope 이란 범위
를 뜻한다.
그리고 프로그래밍 언어에서 Scope이란 어떠한 객체 (변수, 함수 등)가 유효한 범위
를 의미한다. ! 범위를 벗어나면 해당 객체는 사용되지 못한다 !
Python에서는 Scope을 그림과 같이 4개 범위로 나눌 수 있다.
어떤 범위가 가장 제한적이고, 가장 광범위한지는 그림을 통해서 충분히 이해 할 수 있다.!!
그리고 미리 말하지만 이러한 Scope은 해당 객체가 처음 정의된 Scope에 대해서 제한적이지 않고 상대적이다. (객체의 위치에 따라 Scope의 범위가 변할 수 있다는 의미)
가장 제한적인 범위(Scope)이다.
def func():
a = 1
print(a)
이 함수에서 변수 a가 유효한 범위는 func()안의 코드 두 줄이다.
함수 안에서 선언되었디 때문이다. 즉, local scope
이다.
만약 위의 a 변수가 func()함수 밖에 print(a)로 존재한다면 제대로 출력이 될까?
def func():
a = 1
print(a)
-> NameError: name 'a' is not defined
당연한 결과지만 a 를 정의할 수 없다는 에러가 뜬다.(NameError)
중첩함수가 있을때 적용되는 Scope이다.
부모함수에서 선언된 변수를 중첩함수 안에서도 유효한 범위를 갖고 있다.
def func():
a = 1
print(a)
def inner():
b = 7
print(a * b)
inner()
위 구조에서 변수 a는 a=1
부터 inner()
까지 유효하다.
(변수 a는 enclosing scope으로 inner()함수 속에서도 유효하다!)
그에비해 변수 b는 local scope으로써 inner()함수 속의 b=7
부터 print(a * b)
까지만 유효하다.
만약위의 구조에서 변수 b를 inner()함수 밖에서 사용하면 어떻게 될까?
def outer():
a = 1
print(a)
def inner():
b = 7
print(a * b)
inner()
print(b)
-> NameError: name 'b' is not defined
함수 "안"이 아닌 함수 밖에서 선언된 변수나 함수를 이야기 한다.
-> 해당 파일의 가장 바깥에서 선언
되었으므로 선언된 지점 아래로는 다 유효한 scope를 갖고있다.
g = 8
def outer():
a = 1
print(a+g)
def inner():
b = 7
print(a * b * g)
inner()
위 구조와 같이 함수 밖에서 선언된 변수 g는 선언 지점 아래로 모두 유효함으로 함수 / 중첩함수 내에서도 모두 유효하다.
가장 광범위한 Scope이다. 우리가 작성하는 것이 아니라 Python 안에 내장되어 Python이 제공하는 함수 또는 속성들
을 의미한다.
때문에 별다른 선언 없이 모든 python 파일에서 유효한 scope을 갖고 있다.
동일한 이름의 변수들이 서로 다른 scope에서 선언이 되면 더 좁은 범위에 있는 변수(혹은 함수)가 더 넓은 범위에 있는 변수를 가리는 (shadowing)효과
어떤 함수/변수의 값을 찾기 위해 python에서는 local ---> builtin 순으로 찾는다.
좁은 범위 ---> 광범위한 범위 임을 잊지말자!!
동일한 범주에 속하는 대상들을 일정한 기준에 따라 나누어 놓은 갈래
과일 에는 사과, 바나나, 수박이 있다.
그렇다면 여기서 Class 는 ? 과일 이 된다.
그러면 과일 class에 속하는 사과, 바나나, 수박은 뭐라고 부르는가 ? 이것들은 실체(instance)들이다.! 이것들을 객체(object)라고 부른다.
그 다음 내용은 추가할꺼임 ~^*^