Notice
Recent Posts
Recent Comments
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
10-11 00:15
Archives
Today
Total
관리 메뉴

Developer_Neo

[python] 네스티드 함수와 클로저, 데코레이터, 클래스 메소드와 static메소드 본문

프로그래밍/Python

[python] 네스티드 함수와 클로저, 데코레이터, 클래스 메소드와 static메소드

_Neo_ 2022. 1. 20. 16:21
반응형

네스티드 함수(Nested Function)

- 중첩 함수로써  함수 안에 정의된 함수를 의미한다.

예로 살펴보자

def maker(m):
	def inner(n):
    	return m*n
    return inner

fl=maker(2)
f1(7)
# 14

위에서 inner함수가 네스티드 함수가 된다.

 

이게 왜 가능하냐?

파이썬의 함수는 객체이다 이렇기 때문에 다른함수를 호출할때 인자로도 전달이 가능하기 때문이다.

 

 

위의 코드에서 maker함수에서 m이 벗어나면 m은 사라지게 되는데 어떻게 inner함수가 알고선 계산을 올바르게 하는가?

클로저로 알아보자

 

클로저

위의 질문에 답변을 해보자면 정의한 inner함수가 변수 m의 값을 어딘가에 살짝 저장해두고 쓴다는 것이다. 

 

따라서 안쪽에 위치한 네스티드 함수가 자신이 필요한 변수의 값을 어딘가에 저장해 놓고 쓰는 태크닉을 클로저라고 한다.

 

사용메소드 __closure__[ ? ].cell_contents

 

저장된 위치를 확인해 보자

>>>def maker(m):
	   def inner(n):
    	   return m*n
       return inner

>>> f1 = maker(101)
>>> f2 = maker(75)

>>> f1.__closure__[0].cell_contents
101
>>> f2.__closure__[0].cell_contents
75

위의 코드와 같이 m값을 저장해 놓는 위치는 각각 101 75에 해당하게 된다.

 

 


데코레이터

- 꾸며주는 (덧붙여주는) 역할을 하는 함수 또는 클래스를 뜻한다.

 

형식

- 데코레이터 함수를 선언을 하는데 네스티드함수가 포함되게 정의한다.

  그리고 데코레이터 함수의 인자로 들어갈 함수위에 @데코레이터함수이름 으로 작성뒤 함수를 만든다.

  출력을 할 때에는 데코레이터 함수 인자이름을 기반으로 작성한다.

def adder_deco(func):       # 데코레이터 함수
    def ad(*args):
        print(*args, sep = ' + ', end = ' ')
        print("= {0}".format(func(*args)))
    return ad


@adder_deco
def adder2(n1, n2):       # 전달 인자가 두 개인 함수
    return n1 + n2

@adder_deco
def adder3(n1, n2, n3):       # 전달 인자가 세 개인 함수
    return n1 + n2 + n3


def main():
    adder2(3, 4)
    adder3(3, 5, 7)

main()

데코레이터 함수의 인자로 들어갈 함수는 인자를 받을 수도 있고 안받을 수도 있는데 네스티드함수에서 넘겨주는 인자

 

가 있을 경우에는 인자를 받는다.

 

 

데코레이터를 두번 이상 통과 시킬수도 있다.

def deco1(func):       # 데코레이터 1
    def inner():
        print('deco1')
        func()
    return inner

def deco2(func):       # 데코레이터 2
    def inner():
        print('deco2')
        func()
    return inner

@deco1
@deco2
def simple():
    print('simple')


def main():
    simple()

main()

'''
deco1
deco2
simple
'''

 

 

 


클래스 메소드와 static메소드

 

클래스 변수 VS 인스턴스 변수

 

클래스 변수

- 그냥 클래스에 넣은 변수 

인스턴스 변수

- 생성자인 __init__으로 생성되는 변수

Class simple:
	cv=20                    #클래스변수
	def __init__(self):
    self.iv=10               #인스턴스변수

클래스변수는 객체를 통해서도 접근이 가능하고 그냥 클래스이름.변수 형태로도 접근이 가능하다.

#클래스 변수
Simple.cv
20
s = Simple()
s.cv

s.iv   #인스턴스변수는 객체를 통해서만 접근

그런데 가끔가다가 cv가 클래스 변수인지 인스턴스 변수인지 구분이 안될때가 있다.

 

그렇기 때문에 클래스 변수는 클래스 이름을 토한 접근을 권한다고 한다.

 

그리고 클래스 변수에 해당하는 것static변수처럼 클래스에 속한 변수로써 

 

객체가 늘어남에 따라 각각 클래스변수를 가지고 있는것이 아닌 공유한다.

 

static메소드

- static은 클래스가 생성되지 않아도 호출이 가능한것으로써 프로그램이 run하게 되면 그때 같이 생겨서 호출이 가능하다.

- 클래스에 속한다 객체에 속하는 것이 아닌.

- static메소드는 첫번째 인자로 self를 전달 받지 않는다. 그래서 staticmethod라는 것을 거쳐야한다.

class Simple:
    # @staticmethod
    def sm():
        print('static method!')

    sm = staticmethod(sm) # static메소드의 이름과 같게


def main():
    Simple.sm()  #static이기 때문에 가능
    s = Simple()
    s.sm() #원래 가능

main()

 

클래스 메소드

이것도 또한 self를 전달 받지 않는다 하지만 인자로 class에 해당하는 것을 설정은 해두는데 인자로 받지는 않는다.

Class Simple:
	@classmethod
    def cm(cls):
		print('pass')

Simple.cm()
# pass

클래스 메소드의 첫번째 인자로 전달되는 것은 그 메소드의 클래스이다.

 

클래스 메소드와 static메소드

데코레이터로 알아보자

@staticmethod  static 메소드를 만들기 위한 데코레이터

@classmethod   클래스 메소드를 만들기 위한 데코레이터

 

class Natural:
    def __init__(self, n):
        self.n = n

    def getn(self):
        return self.n
    

    @classmethod
    def add(cls, n1, n2):
        return cls(n1.getn() + n2.getn())
        
def main():
    n1 = Natural(1)
    n2 = Natural(2)
    n3 = Natural.add(n1, n2)
    print('{0} + {1} = {2}'.format(n1.getn(), n2.getn(), n3.getn()))

main()

 위에서 cls(n1.getn() + n2.getn()) 에 해당하는 부분은 Natural(n1.getn() + n2.getn()) 와 같다.

 

이것과 관련된 자세한 예는 윤성우의 열혈 파이썬 중급편 223~226쪽을 보길 바란다.

 

 

 

참고한 책 : 윤성우의 열혈 파이썬 중급편

반응형
Comments