티스토리 뷰

728x90

클래스는 데이터(속성, attribute)와 그에 대한 처리를 하나로 정의한 것으로 파이썬 오브젝트들은 특정 클래스의 인스턴스들 입니다. 클래스의 인스턴스인 오브젝트는 다음와 같은 생애주기를 갖습니다.


    • 정의
      class 문을 통해 클래스를 정의.(시스템 클래스도 마찬가지)

    • 생성
      정의한 클래스 정의에 따라 오브젝트를 생성하고 __init__를 호출하여 속성을 초기화.

    • 작업
      메쏘드 또는 메쏘드 함수를 통하여 작업을 수행.

    • 정리(Garbage Collection)
      더이상 사용하지 않는 오브젝트를 정리.


■ 클래스 정의


클래스 정의는 아래와 같은 문형을 갖습니다.


class 클래스명(부모 클래스):

코드 블럭


클래스명은 변수명 규칙을 따르지만 클래스명은 첫문자를 대문자로 해서 혼란을 방지 하는 것이 좋습니다. 메쏘드나 속성은 소문자로 작성 합니다. 부모 클래스는 상속 받을 클래스를 기술하는데, 단순하게 object를 기술해도 되고 괄호를 통째로 생략할 수도 있습니다.


코드 블럭에는 함수 정의에서 언급했던 Docstring이("""....""" 방식으로 문서화 정보 기술) 올수 있고("파이썬 함수 - 파이썬 배우기(Python)" 참조), 함수정의와 대입문을 통한 속성 정의가 올 수 있습니다다. 속성 정의에서 변수명 앞에 __를 붙이면 클래스 외부에서 해당 속성을 접근할 수 없도록 숨겨 집니다. 실제로 내부적으로도 이름을 변경해서 저장 합니다. 그렇지만 이것은 단순한 이름 변경이고 다른 OOP언어에서의 private과 같은 개념을 파이썬은 지원하지 않습니다.


클래스내 함수는 메쏘드 또는 메쏘드 함수라 불리우며 반드시 첫번째 파라미터로 self가 와야 합니다. 


class Bdb:

    """Generic Python debugger base class.

    This class takes care of details of the trace facility;
    a derived class should implement user interaction.
    The standard debugger class (pdb.Pdb) is an example.
    """

    def __init__(self, skip=None):
        self.skip = set(skip) if skip else None
        self.breaks = {}
        self.fncache = {}

    def canonic(self, filename):
        if filename == "<" + filename[1:-1] + ">":
            return filename


위의 코드는 bdb 모듈의 내장 클래스 Bdb 일부 입니다.



■ 클래스 인스턴스 정의와 사용


"a = MyClass()" 처럼 클래스 이름에 함수 호출처럼 기술하는 방식으로 클래스의 인스턴스를 생성하여 리턴 합니다. 메쏘드를 사용할 때는 생성한 오브젝트명.메쏘드의 형식으로 사용 합니다. 


속성은 클래스 레벨로 정의된 클래스 속성(예제에서 attr1)과 인스턴스 레벨로 사용할 수 있는 인스턴스 속성이(예제에서 attr2) 있는데 인스턴스 속성은 동일 클래스로 부터 생성 되었다 하더라도 서로 다른 인스턴스 간에는 상호 접근할 수 없습니다. 메쏘드 내에서 self.속성은 인스턴스 속성을 지칭 합니다.  클래스 속성은 오브젝트명.속성과 클래스명.속성으로 모두 사용할 수 있는데 오브젝트명.속성으로 기술한 경우에 동일한 이름의 인스턴스 속성이 있으면 인스턴스 속성을 클래스 속성에 우선하여 접근 합니다.


dir(인스턴스명)으로 인스턴스를 통해 사용할 수 있는 모든 속성을 받을 수 있습니다.


>>> class MyClass:

attr1 = 100

def mf1(self, n) :

self.attr2 = n+2

return n+2

def mf2(self, n) :

self.attr2 = n*2

return n*2

>>> MyClass.attr1

100

>>> a = MyClass()

>>> a.attr1

100

>>> a.mf1(10)

12

>>> a.attr2

12




■ 특별한 메쏘드


아래의 메쏘드들은 시스템에서 특별한 용도로 사용하는 메쏘드들로 클래스 내부에 해당 이름의 메쏘드를 정의해 두면 해당 클래스에 대한 작업을 자연스럽게 적용할 수 있게 됩니다.


    • __init__
      클래스 인스턴스 생성후 초기화 작업을 위해 자동 호출 됩니다. __init__ 함수의 파라미터는 클래스 인스턴스 생성시 전달해야 하는 파라미터와 일치 합니다.

      >>> class MyClass:


      attr1 = 100

      def __init__(self, at):

      MyClass.attr1 = at

      def mf1(self, n) :

      self.attr2 = n+2

      .....

      >>> a = MyClass(30)

      >>> a.attr1

      30

    • __del__
      인스턴스가 소멸될 때 호출되는 것으로. Garbage Collection 에서 자동 정리 하므로 많이 사용하지는 않습니다.
    • __str__
      print문에 해당 클래스가 인수로 등장했을때 호출 됩니다. str(오브젝트) 형변환 일 때도 호출 됩니다.
    • __int__, __long__, __float__, __oct__, __hex__, __complex__
      클래스에 대한 형변환 요청시 호출 됩니다.
    • __repr__
      인스턴스의 자세한 값을 보고 싶을때 사용하는 repr(오브젝트)을 사용할 때 호출 됩니다.
    • __cmp__
      리스트내 정렬, 오브젝트간 비교등의 작업시에 호출 됩니다.
      메쏘드를 작성하는 경우 1, 0 ,-1 중 하나를 리턴 합니다.
    • __add__
      오브젝트에 + 연산자를 사용했을때 호출 됩니다. + 연산자 좌측에 있을때 호출되고
      우측에 있을때는 __radd__, +=는 __iadd__  아래는 
    • __sub__
      - 연산자, __rsub__, __isub__
    • __mul__
      * 연산자, __rmul__, __imul__
    • __div__
      / 연산자, __rdiv__, __idiv__
    • __mod__
      % 연산자, __rmod__, __imod__
    • __pow__
      ** 연산자, __rpow__, __ipow__
    • __coerce__
      클래스에 대한 이항 연산 수행전에 호출되어 사전 작업이 가능하도록 지원 합니다. __coerce__ 메쏘드를 정의할 때 리턴에는 두개의 파라미터를 넘겨야 합니다.
    • __len__
      len() 수행시 호출 됩니다.
    • __nonzero__
      bool(객체)등의 경우처럼 객체가 참인지 거짓인지를 판별할때 호출 됩니다.True 또는 False 리턴
    • __contains__
      in  수행시 호출 됩니다.
    • __getitem__
      오브젝트[키] 식으로 참조하는 경우 호출 됩니다. for  in 문장, list(), tuple() 변환시에도 호출 됩니다.
    • __setitem__
      오브젝트[키]=값 식으로 값을 설정하는 경우
    • __delitem__
      del 오브젝트[키] 식으로 삭제하는 경우
    • __getattr__
      존재하지 않는 인스턴스 속성을 참조할때 호출 됩니다. 자신의 클래스에 속하지 않는 함수나 속성을 참조할때 발생하므로 이때 적절한 코드를 수행하여 위임(Delegation)을 구현할 수 있습니다.
    • __setattribute__
      인스턴스 속성에 값을 대입 할 때 호출 됩니다.
    • __delattr__
      인스턴스 속성을 삭제 할 때 호출 됩니다.
    • property(참조함수, 설정함수, 삭제함수, Docstring)
      속성에 대한 처리를 수행하는 함수들을 인수로 하여 속성 타입을 리턴 합니다. 클래스 정의시 속성 타입의 속성을 정의 할 때는 참조 및 설정 메쏘드를 먼저 정의하고 property 타입은 속성의 참조 설정 등을 처리 할 메쏘드만을 관리 하므로 별도의 인스턴스 속성을 관리하는 등의 처리과정이 있어야 합니다.  단, 클래스는 object로 부터 상속을 받아야 합니다.
    • __call__
      클래스 인스턴스명 자체로 함수처럼 사용할 때 호출 됩니다. __call__ 메쏘드를 정의한 클래스의 인스턴스는 callable(인스턴스)에 True를 리턴 합니다.
    • __slots__
      클래스의 인스턴스에는 동적으로 인스턴스를 속성을 정의해 사용할 수 있고 이들은 인스턴스명.__dict__로 확인할 수 있습니다. 그런데 미리 정해진 속성만 사용하도록 강제할 수도 있는데 클래스 정의시 "__slots__ = ['속성명',....]" 방식으로 기술해 놓으면 됩니다. 단, 클래스는 object로 부터 상속을 받아야 합니다. __slots__를 사용하면 __dict__는 사용하지 않습니다.
    • 정적메쏘드
      일반적으로 메쏘드는 오브젝트에 대해서만 사용할 수 있는데 메쏘드를 정의 할 때  첫 인수로 self를 사용하지 않은 상태로 기술한 다음 "메쏘드명 = staticmethod(메쏘드명)"의 형식으로 지정하면 해당 메쏘드를 인스턴스 없이 클래스명.메쏘드로 직접 사용할 수 있습니다.
    • 클래스메쏘드
      첫인수가 self인 일반 메쏘드들은 메쏘드를 호출하면 해당 인스턴스를 넘겨받는데, 인스턴스 대신 클래스를 전달받을 수도 있고 인스턴스 없이 메쏘드 호출이 가능 합니다. self 대신 클래스를 받을 인수를 정의하고 "메쏘드명 = classmethod(메쏘드명)"의 형식으로 지정해 주면 됩니다.
    • 장식자(decorator)
      정적메쏘드나 클래스메쏘드를 정의하는 방법 대신 메쏘드 상단에 "@장식자"의 형식으로 기술하는 방법으로 Aspect-oriented programming의 개념이 적용된 것입니다. 파이썬에서 장식자는 일종의 함수로 메쏘드 앞에 적용되어 기존 함수를 다른 함수로 전환시켜주는 역할을 합니다. 시스템에서 기본 제공하는 장식자는 앞서 사용한 @staticmethod, @classmethod가 있고 사용자가 직접 정의해서 타입 검사나 함수 디버깅 등에 다양한 용도로 사용할 수 있습니다. 아래는 장식자를 정의하는 방법입니다.
def 장식자이름( 함수인수 ):
   def 내부함수명( *args, **keywords ):
함수인수_개선코드...   
    함수인수(args, keywords) # 기존 함수 호출
함수인수_개선코드...
   내부함수명.__name__= 함수인수.__name__
   내부함수명.__doc__= 함수인수.__doc__
   return 내부함수명


위에서 정의한 장식자를 메쏘드위에 "@장식자이름" 으로 지정하면 함수 인수로 해당 메쏘드가 전달되고 메쏘드의 인수들은 args, keywords로 전달되어 개선 코드와 함께 원래의 메쏘드가 호출되는 방식 입니다. 아래는 함수 호출 로깅을 위한 좋은 장식자 예제 입니다.


def trace( aFunc ):

    """Trace entry, exit and exceptions."""

    def loggedFunc( *args, **kw ):

        print "enter", aFunc.__name__

        try:

            result= aFunc( *args, **kw )

        except Exception, e:

            print "exception", aFunc.__name__, e

            raise

        print "exit", aFunc.__name__

        return result

    loggedFunc.__name__= aFunc.__name__

    loggedFunc.__doc__= aFunc.__doc__

    return loggedFunc


특정 함수 앞에 장식자를 기술해 놓으면 해당 함수가 호출되는 시점(진입점), 종료점과 함께 예외 발생시에도 추적 정보를 출력하는 방식입니다.

class MyClass( object ):

    @trace

    def __init__( self, someValue ):

        """Create a MyClass instance."""

        self.value= someValue

    @trace

    def doSomething( self, anotherValue ):

        """Update a value."""

        self.value += anotherValue


위의 코드는 앞서 정의한 장식자를 사용한 예제입니다.


장식자에 파라미터를 넘겨줄 경우에는 위에서 정의한 장식자 정의를 포함하고 인수는 장식자로 넘겨지는 파라미터를 받고 내포하는 장식자 함수 값을 리턴하는 형태로 정의하면 됩니다. 아래는 디버깅 옵션을 인수로 전달받는 장식자 정의 예제 입니다.


def debug( theSetting ):

    def concreteDescriptor( aFunc ):

        if theSetting:

            def debugFunc( *args, **kw ):

                print "enter", aFunc.__name__

                return aFunc( *args, **kw )

            debugFunc.__name__= aFunc.__name__

            debugFunc.__doc__= aFunc.__doc__

            return debugFunc

        else:

            return aFunc

    return concreteDescriptor






728x90
댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/04   »
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
글 보관함