"프로그래밍 언어의 개념과 흐름에 대한 고찰 - 파이썬답게 코딩하기" 학습중...


함수와 관련하여 어렴풋이 알던 내용들 몇가지 정리해봅니다.


Nested Function에 대하여


## Nested Function
## 내부 함수는 외부 함수의 메모리 접근이 가능하나 외부 함수는 내부 함수를 직접 호출할 수 없다.
#!/usr/bin/python3
# def calculator(x, y) :
# def add() :
# return x + y
# def sub() :
# return x - y
#
# return (add(), sub())
#
# if __name__ =="__main__" :
# print("=== print calculation ===")
# print(calculator(10, 5))

## === print calculation ===
## (15, 5)




# def calculator(x) :
# def add(y) :
# return x + y
# return add
#
# if __name__ =="__main__" :
# print("=== print calculation ===")
# f = calculator(10)
# print(f(5))
# print(f(10))

## === print calculation ===
## 15
## 20



Closure에 대해


## Closure
## 중첩 함수의 일종. 함수의 반환값으로 내부 함수를 사용하는 함수.

# def multiple_of_ten() :
# sqr_root = 10
#
# def sqr(x) :
# return sqr_root ** x
#
# return sqr
#
# def main() :
# print("=== print result ===")
# f = multiple_of_ten()
# print(f(2))
# print(f(3))
#
# if __name__ == "__main__" :
# main()
## === print result ===
## 100
## 1000



Closure가 가능한 이유에 대해 고찰해봅니다.


## Closure Attribute를 알아보기 전에 일반 함수의 속성을 먼저 본다.

# def normal_func() :
# pass
# if __name__ == "__main__" :
# p = dir(normal_func())
# print("=== attribute===")
# print(p)
## === attribute===
## ['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__
## lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']



Nested 함수의 속성을 알아봅니다. 내부 함수, 외부 함수 속성이 같습니다.


# def nested_function() :
# def inner() :
# pass
#
# p = dir(inner())
#
# print("=== inner attribute ===")
# print(p)
#
# if __name__ == "__main__" :
# p = dir(nested_function())
# print("=== attribute ===")
# print(p)

## === inner attribute ===
## ['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__
## lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
## === attribute ===
## ['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__
## lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']




# def closure() :
# def inner() :
# pass
#
# p = dir(inner())
#
# print("=== inner attribute ===")
# print(p)
# return inner
#
# if __name__ == "__main__" :
# p = dir(closure())
# print("=== attribute ===")
# print(p)

## === inner attribute ===
## ['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__
## lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
## === attribute ===
## ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__
## getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__
## ', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
## 위의 결과 출력에서 '__closure__' 속성이 추가되었는데 이 곳에서 내부 함수가 사용하는 nonlocal 변수들이 저장된다.



nonlocal 변수를 사용하지 않은 경우 __closure__ 속성값이 없습니다.


## non local 변수를 사용하지 않은 경우

# def closure() :
#
# def inner() :
# pass
#
# return inner
#
# if __name__ == "__main__" :
# p = closure()
# print("=== attribute closure ===")
# print(p.__closure__)
## === attribute closure ===
## None



Closure의 사용 목적에 대해


# def closure() :
# x = 10
# def inner() :
# y = 20
# return x + y
# return inner
#
# if __name__ == "__main__" :
# p = closure()
# print("=== attribute closure ===")
# print(p.__closure__[0].cell_contents)

## === attribute closure ===
## 10
## nonlocal 변수 10의 값이 저장됨을 확인할 수 있다. 이렇듯 non local 변수는 global 변수를 사용하고 싶지 않을 때 사용할 수 있다.
## 두번째로는 클래스를 사용하지 않기 위해서. 다루는 변수느 함수가 많지 않은 경우 클래스로 만드는 것 보다 함수로 만드는 것이
## 효율적이고 이 경우 closure로 구현하는 것이 효율적일 수 있다.파이썬은 엄밀히 말하면 객체지향 언어가 아니기 때문에 꼭 모든 것을
## 클래스로 통일할 필요는 없다.
## 끝으로 데코레이터(decorator)를 사용하기 위해서.




## non local 변수를 사용한 경우

# def closure() :
# x = 10
# def inner() :
# y = 20
# return x + y
# return inner
#
# if __name__ == "__main__" :
# p = closure()
# print("=== attribute closure ===")
# print(p.__closure__)

## === attribute closure ===
## (<cell at 0x00000252E585C4C8: int object at 0x0000000052086C30>,)
## 튜플 1개가 출력되는데 이 주소값을 더 확인해보면 아래와 같다.




# def closure() :
# x = 10
# def inner() :
# y = 20
# return x + y
# return inner
#
# if __name__ == "__main__" :
# p = closure()
# print("=== attribute closure ===")
# print(len(p.__closure__))
# print(dir(p.__closure__[0]))

## === attribute closure ===
## 1
## ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne
## __', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
## cell_contents에 대한 값을 확인해보면 아래와 같다.




## nonlocal 변수로 시간과 관련된 값을 사용하게 되면 의도치 않은 결과가 나올 수 있다.

# import datetime
# import time
#
# def logger() :
# now = datetime.datetime.now()
#
# def print_log(msg) :
# return ("[%s] %s" %(now, msg))
#
# return print_log
#
# def main() :
# log = logger()
# print(log("start"))
# time.sleep(10)
# print(log("After 10 sec"))
#
# if __name__ =="__main__" :
# main()

## main 함수 시작시 now값이 저장되었기 때문에 내부 함수도 이 값을 참고하게 되므로 시간 관련 함수에는 주의가 필요하다.
## [2020-08-20 01:20:27.508186] start
## [2020-08-20 01:20:27.508186] After 10 sec



'파이썬(PYTHON)' 카테고리의 다른 글

파이썬의 기본 문법1  (0) 2020.08.21
파이썬의 함수3  (0) 2020.08.21
파이썬의 함수1  (0) 2020.08.19
파이썬의 변수  (0) 2020.08.18
openpyxl 모듈 활용 연습3  (0) 2020.08.16

+ Recent posts