티스토리 뷰

Python

Python, 정적메소드,클래스메소드

hwangyoungjae 2016. 5. 9. 11:05
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

메소드의 확장형태로 정적메소드(static method)와 클래스메소드(class method)가 있다정적 메소드는 인스턴스객체를 통하지 않고 클래스를 통해 직접 호출할수 있는 메소드이다이 경우 메소드 정의시 인스턴스 객체를 참조하는 'self'라는 인자를 선언하지 않는다반면 클래스메소드의 경우 암묵적으로 첫 인자로 클래스 객체가 전달된다.

두 경우 모두 아래오 ㅏ같은 형태로 클래스내에서 등록해야 한다.

<호출할 메소드이름> = staticmethod(클래스내 정의한 메소드이름)

<호출할 메소드이름> = classmethod(클래스내 정의한 메소드이름)

예를 들어 클래스부터 생성되는 인스턴스의 개수를 관리하고 싶은 경우클래스 영역에서 그 정보를 관리하는 것이 가장 효율적일것이다이러한 정보가 저장/출력될수 있도록 다음과 같이 클래스를 정의하였다.

class cm:

    cnt=0

 

    def __init__(self):

        cm.cnt+=1

 

    def printcnt():

        print('instance count : '+str(cm.cnt))

 

a=cm()

b=cm()

c=cm()

 

cm.printcnt()

c.printcnt()

 

실행결과

instance count : 3

Traceback (most recent call last):

  File "D:\Cloude\[Blog]\python.py", line 15, in <module>

    c.printcnt()

TypeError: printcnt() takes no arguments (1 given)

 

위의 예제에서 instance 객체 생성시, instance 개수를 저장하는 클래스 멤버 변수 cnt가 증가되도록 하였다. printcnt() 메소드에서는 인스턴의 개수를 출력하도록 하였다.

인스턴스영역의 값을 참조하지 않기 때문에 메소드정의시 첫 인자로 암묵적으로 받은 인스턴스 객체를 사용하지 않았다.

그결과 클래스를 통하여 호출하는 경우는 정상적으로 수행되나인스턴스 객체를 이용하여 호출하는 경우에는 TypeError가 발생하는것을 확인할수 있다.

위와 같은 Error가 발생하지 않도록 하기 이하여 정적메소드와 클래스메소드를 이용하여 다음과 같이 다시 작성하였다.

class cm:

    cnt=0

    def __init__(self):

        cm.cnt+=1

 

    def s_printcnt(): #정적메소드정의

        print("instance count : "+str(cm.cnt))

    sprintcnt=staticmethod(s_printcnt)

 

    def c_printcnt(cls): #클래스메소드정의(암묵적으로 첫인자는 클래스를받음)

        print("instance count : "+str(cls.cnt))

    cprintcnt=classmethod(c_printcnt)

 

a=cm()

b=cm()

c=cm()

 

cm.sprintcnt() #staticmethod로 인스턴스객체개수 출력

c.sprintcnt()

 

cm.cprintcnt() #classmethod로 인스턴스객체개수 출력

c.cprintcnt()

 

실행결과

instance count : 3

instance count : 3

instance count : 3

instance count : 3

 

정적메소드로 출력하는 경우 암묵적으로 받는 첫인자가 필요하지 않는다이렇게 정의한 메소드는 정적메소드로 등록을 해야하며호출시 등록된 이름으로 호출하여야 한다클래스메소드의 경우 첫인자는 암묵적으로 클래스 객체가 되며이 역시 클래스 메소드로 등록을 하여야 호출시 암묵적으로 클래스객체를 전달한다이렇게 정의된 정적메소드와 클래스메소드는 클래스뿐만 아니라 인스턴스 객체를 통해서도 호출이 가능하다.

 

※ 일반적인경우 첫인자를 암묵적으로 인스턴스를 반환한다.

staticmethod의 경우 첫인자에 아무것도 반환하지 않는다.

classmethod의 경우 첫인자를 암묵적으로 클래스를 반환한다.

 

※ 위처럼 staticmethod,classmethod를 메소드처럼 사용할수도 있지만 문법형식으로 사용할수도 있다.

class cm:

    cnt=0

    def __init__(self):

        cm.cnt+=1

 

    @staticmethod #정적메소드로정의

    def s_printcnt():

        print("instance count : "+str(cm.cnt))

 

    @classmethod

    def c_printcnt(cls): #클래스메소드정의(암묵적으로 첫인자는 클래스를받음)

        print("instance count : "+str(cls.cnt))

 

a=cm()

b=cm()

c=cm()

 

cm.s_printcnt() #staticmethod로 인스턴스객체개수 출력

c.s_printcnt()

 

cm.c_printcnt() #classmethod로 인스턴스객체개수 출력

c.c_printcnt()

 

실행결과

instance count : 3

instance count : 3

instance count : 3

instance count : 3

 

※ 이름변경(Naming Mangling )

위의 cm클래스에서 멤버변수 'cnt'는 인스턴스객체의 개수를 저장하는것으로 매우 중요한 변수이다그러나 파이썬에서는 기본적으로 'public'속성을 갖기때문에 다음과 같이 클래스의 외부에서 접근변경이 가능하다.

>>> print(cm.cnt) #클래스외부에서 변수에 접근하는 경우

3

>>> cm.cnt=999 #클래스외부에서 변수의 값을 변경하는 경우

>>> cm.c_printcnt()

instance count : 999

파이썬에서는 '이름변경(Naming Mangling)'으로 그 문제점을 해결하였다즉 클래스 내의 멤버변수나 함수를 정의할때 '__'로 이름을 시작하는 경우클래스 외부에서 참조할때 자동적으로 '_[클래스이름]__[멤버이름]'으로 변경된다물론 클래스네에서는 정의한 이름인 '__[멤버이름]'만으로 사용이 가능하다.

class cm:

    __cnt=0 #이름변경을 위하여 '__'를 변수명 앞에 사용

    def __init__(self):

        cm.__cnt+=1

 

    @staticmethod

    def s_printcnt():

        print('instance count : %d' % cm.__cnt) #클래스내부에서 사용시 선언한 이름과 동일하게 사용

a=cm();b=cm();c=cm()

cm.s_printcnt()

c.s_printcnt()

 

실행결과

instance count : 3

instance count : 3

 

이렇게 이름변경이 적용된 멤버변수에 그 이름을 사용하여 외부에서 접근하는 경우클래스 내에 동일한 이름이 없다는 NameError가 발생한다.

물론 변경된 이름(_cm__cnt)으로 접근하는 경우 그 변수에 대한 읽기쓰기가 가능하다.

즉 파이썬에서는 문법의 제약사항으로 정보은닉기능을 제공하기 보다는 이름변경으로 개발자의 의도를 나타내도록 하였다그렇기 때문에 변경된 이름으로 그 변수에 접근하여 사용하는 것을 장려하지는 않는다.

>>> print(cm.__cnt) #NameError발생

Traceback (most recent call last):

  File "<pyshell#38>", line 1, in <module>

    print(cm.__cnt)

AttributeError: type object 'cm' has no attribute '__cnt'

>>> print(cm._cm__cnt)

3

>>> dir(cm)

[생략 '_cm__cnt', 's_printcnt']

 

 

참조 : 빠르게 활용하는 파이썬프로그래밍

 

'Python' 카테고리의 다른 글

Python, 클래스(Class) - 연산자중복정의  (0) 2016.05.09
Python, 클래스(Class)  (0) 2016.05.09
Python, @property  (0) 2016.05.09
Python,module copy [객체복사]  (0) 2016.04.29
Python,module re [정규표현식]  (0) 2016.04.29
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
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
글 보관함