PYTHON CLASS 구구 Moon Yong Joon
PYTHONCLASS구조
Moon Yong Joon
기술적접근
객체
왜 모든 것을 객체로 관리하나 ?
모든 것은 객체
값 문자열컨테이너
함수클래스
튜플리스트
딕션너리
집합
파이썬은 모든 것을 객체로 인식한다 . 데이터 구조가 다 객체이므로 클래스를 가지고 생성시 참조를 가지고 있음
파일모듈 패키지
모듈
객체로 구성했나 ?실제 오퍼페이터를 내부적으로 메소드로 정의되어 있어서 메소드 처리로 인식되고 테이터 타입을 명확히 맞춰서 계산처리 됨
1.+(1) 1
__add__( 객체 )
>>> 1+12>>> >>> 1.+12.0>>> int(1.+1)2>>> >>> p=1>>> p.__add__(1)2>>>
클래스 정의
Class Notation파이썬 언어에서 객체를 만드는 타입을 Class 를 정의하여 사용
클래스 명변수
메소드
class 클래스이름 [( 상속 클래스명 )]:
< 클래스 변수 1> < 클래스 변수 2> ... def 인스턴스 메소드 (self[, 인수 1, 인수 2,,,]): < 수행할 문장 1> < 수행할 문장 2> ... def 클래스메소드 (cls[, 인수 1, 인수 2,,,]): < 수행할 문장 1> < 수행할 문장 2> ... def 정적메소드 ([, 인수 1, 인수 2,,,]): < 수행할 문장 1> < 수행할 문장 2> ...
Instance Notation인스턴스 객체는 실제 클래스 객체가 생성시 할당인스턴스 변수와 메소드는 런타임 즉 실행시 등록하여 사용할 수 있음
인스턴스명 : 클래스명인스턴스 변수
인스턴스 메소드( 인스턴스 바인딩 경우 )
class 클래스이름 [( 상속 클래스명 )]: def __init__(self[, 인수 1, 인수 2,,,]): self. 변수명 = 인수 1 …… < 수행할 문장 2> ... def 인스턴스메소드 (self[, 인수 1, 인수 2,,,]): < 수행할 문장 1> < 수행할 문장 2> ... ...
Instance 명 = 클래스명 ( 초기인자들 )
Class 로 Instance 처리파이썬 언어에서 객체를 만드는 타입을 Class 로 생성해서 처리Class 는 객체를 만드는 하나의 틀로 이용자바 언어와의 차이점은 Class 도 Object 로 인식
Class Object
Instance Object 1
Instance Object 2
Instance Object 3
instanciate
클래스에서 객체 생성하기
New style classObject 를 상속하여 명확히 클래스들이 표시됨 import types
class A(object) : def __init__(self,name) : self.name = name a = A('dahl')print a.name
print(" instance type ", type(a))print(types.ClassType == type(A))print(type(a) is types.InstanceType)print(" class type ", type(A))print(" class type ", a.__class__.__bases__)print(isinstance(a,object))print(isinstance(a,type))
dahl(' instance type ', <class '__main__.A'>)FalseFalse(' class type ', <type 'type'>)(' class type ', (<type 'object'>,))TrueFalse
Old style classObject 를 상속할 경우 old style class 로 표시되어 classobj 로 처리되 인스턴스는 intance 타입을 가짐
Import typesclass B(): def __init__(self,name) : self.name = name
b = B('moon')print type(b)print(" class type ", type(B))print(type(b) is types.InstanceType)print(types.ClassType == type(B))
<type 'instance'>(' class type ', <type 'classobj'>)TrueTrue
Instance 생성자
생성자 사용법__new__
__init__
새 인스턴스의 생성을 제어 할 필요시 사용 __new__ 인스턴스 생성의 첫 단계 __new__ 는 첫 번째 인수로 클래스를 받고 , 해당 유형의 새 인스턴스를 반환 mutable 및 immutable 유형 모두 사용
새 인스턴스의 초기화를 제어해야하는 경우 사용 __init__ 아무것도 반환하지 없음 __init__ 는 첫 번째 인수로 인스턴스를 받아 해당 인스턴스의 속성을 수정 . OBJ .__ 초기화 __ (* 인수 ) 를 호출하여 작성 후 수정 될 수 있음 mutable 의 유형에 사용
생성자 형식__new__(...) T.__new__(S, ...) -> a new object with type S, a subtype of T__new__
__init____init__(...) x.__init__(...) initializes x; see help(type(x)) for signature
생성자 사용법 예시__new__ 실행 후에 인스턴스를 만들고 __init__으로 초기화
class C(object) : def __new__(cls) : return super(C, cls).__new__(cls) def __init__(self,name) : self.name = name
c = C.__new__(C)print cprint type(c)print c.__class__print isinstance(c,C)
c.__init__('dahl')print c.name
# 결과값<__main__.C object at 0x10495670><class '__main__.C'><class '__main__.C'>Truedahl
__new__ 메소드 예시클래스로 가변과 불변 타입에 상관없이 새로운 인스턴스만 생성함
# 불변 인스턴스 생성pp = int.__new__(int,0)print("data type", type(pp))print(pp)
# 가변 인스턴스 생성ss = list.__new__(list,[])print("data type", type(ss))
# 가변인스턴스 초기화ss.__init__([1,2,3])print(ss)
# 결과값data type <type 'int'>0data type <type 'list'>[1, 2, 3]
__new__ 메소드 : 예시 2사용자 정의 클래스를 만들고 생성한 후에 초기값 세팅하는 처리
# 클래스 생성class S(object) : pass print("S type ",S)
clss = object.__new__(S)clss.__init__()
# 클래스의 인스턴스 여부 확인print(type(clss), isinstance(clss,S))
# 결과값S type <class '__main__.S'><class '__main__.S'> True
__init__ 메소드 예시불변 인스턴스는 생성되면 초기화가 되지 않음가변은 초기화가 변경됨
# 튜플은 불변이므로 초기화 무시x=(1,2)x.__init__([3,4])print(x)
# 리스트는 가변이므로 초기화 됨y=[1,2]y.__init__([3,4])print(y)
# 결과값(1, 2)[3, 4]
인스턴스 즉시 호출
인스턴스 속성 미정의 후 생성클래스 생성자에 인스턴스 즉시호출 속성을 미정의하고 인스턴스를 호출시 실제 인스턴스가 없으므로 오류처리
>>> class A: ... def __init__(self): ... print "From init ... " ... >>> a = A()From init ...>>> a() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: A instance has no __call__ method>>>
인스턴스 속성 미정의 후 호출인스턴스 속성 미정의할 경우 반드시 인스턴스 처리하는 __call__ 메소드를 정의하여 처리해야 함
>>> class B:... def __init__(self):... print "From init ... "... def __call__(self):... print "From call ... "... >>> b = B()From init ... >>> b()From call ... >>>
__init__ 과 __call__ 메소드 차이클래스 생성자에 따른 인스턴스를 초기화하고 즉시 인스턴스가 실행될 필요가 있을 경우 __call__ 처리
class D: def __init__(self): print "init" def __call__(self): print "call" D() # init D()() # init call
d = D() #initd() # call
생성자와 인스턴스 호출 메소드 정의
생성자와 인스턴스 호출 메소드 정의
object class 이해하기
object classObject class 내의 속성 확인하기
>>> dir(object)['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
object class -1Object class 내의 기본 속성 확인하기
print object.__class__print object.__doc__print object.__str__("objct")print int.__repr__(1)print object.__format__("1234","4.2s")
<type 'type'>The most base type'objct'112
object class -2Object class 내의 생성 및 호출 속성 확인하기
print object.__new__p = list.__new__(list)p.__init__([1,2])
print object.__init__, pprint object.__call__i = int.__call__(5)print i
<built-in method __new__ of type object at 0x1E2296E0><slot wrapper '__init__' of 'object' objects> [1, 2]<method-wrapper '__call__' of type object at 0x1E2296E0>5
object class -3Object class 내의 속성 핸들링 속성 확인하기
class A(object) : def __init__(self) : self.name = None self.age = Nonea = A() print a.__dict__ print object.__delattr__(a,"age")print object.__setattr__(a,"name",'dahl')print object.__getattribute__(a,"name")print a.__dict__
{'age': None, 'name': None}NoneNonedahl{'name': 'dahl'}
object class -4Object class 내의 속성에 메모리 사이즈 및 주소 속성 확인하기
p = list.__new__(list)p.__init__([1,2])print object.__hash__(id(p))print object.__sizeof__(p)
-214166312220
Class Member
Class MemberClass Object 는 클래스 메소드 , 정적메소드 , 클래스 내부 변수 등을 관리한다 .
class Class_Member : cls_var = 0 @classmethod def cls_method(cls) : cls.cls_var = 1 print("call cls_method ", cls.cls_var)
@staticmethod def sta_method() : cls_var = 100 print("call sta_method ", cls_var)
def ins_method(self) : self.ins_var = 1 print('call ins method ', self.ins_var)
c = Class_Member()c.ins_method()print(c.__dict__)
클래스 변수클래스 객체 메소드클래스 정적 메소드
# 처리결과('call cls_method ', 1)('call sta_method ', 100)#Class_Member 내부 관리 영역{'sta_method': <staticmethod object at 0x0215A650>, '__module__': '__main__', 'ins_method': <function ins_method at 0x029D2270>, 'cls_method': <classmethod object at 0x01D92070>, 'cls_var': 1, '__doc__': None}
인스턴스 메소드
Predefined Class At-tributes
Attribute Type Read/Write Description
__dict__ dictionary R/W The class name space.
__name__ string R/O The name of the class.
__bases__ tuple of classes R/O The classes from which this class inherits.
__doc__ string OR None R/W The class documentation string
__module__ string R/W The name of the module in which this class was defined.
Instance MemberInstance 생성시 self 로 정의된 변수만 인스턴스 영역에서 관리하고 인스턴스 메소드는 클래스에서 관리함
class Class_Member : cls_var = 0 @classmethod def cls_method(cls) : cls.cls_var = 1 print("call cls_method ", cls.cls_var) @staticmethod def sta_method() : cls_var = 100 print("call sta_method ", cls_var)
def ins_method(self) : self.ins_var = 1 print('call ins method ', self.ins_var)
c = Class_Member()c.ins_method()print(c.__dict__)
인스턴스 변수
# 처리결과('call ins method ', 1){'ins_var': 1} # 인스턴스 객체 관리 영역
Predefined Instance Attributes
Attribute Type Read/Write Description
__dict__ dictionary R/W The instance name space.
__class__ Base class R The base class
__doc__ string OR None R/W The instance documentation string
클래스와 인스턴스 구조
Object Namespace 흐름Base class
class
in-stance
in-stance
in-stance
상속
인스턴스 생성
Dict{}
Dict{}
Dict{} Dict{} Dict{}
Namespace 검색
객체는 자신들이 관리하는 Namespace 공간을 생성하며 객체 내의 속성이나 메소드 호출시 이를 검색해서 처리
Class & instance scopeClass Object 는 인스턴스를 만드는 기준을 정리한다 . 클래스를 정의한다고 하나의 저장공간 (Namespace) 기준이 되는 것은 아니다 . - 클래스 저장공간과 인스턴스 저장공간이 분리된다
User de-finedClass
Instance
Instance
Instance
Built-inClass
상속 인스턴스화
Object Scope
Object Namespace
Class/Instance 관계 매핑 Class 키워드로 클래스 정의 상속은 class 키워드 다음 () 내에 상속할 클래스 정의 인스턴스 생성은 클래스명에 () 연산자 사용
Super ClassClassinstance
상속인스턴스화
class A(object): def whoami(self): return self.__class__.__name__
a = A()
Class/Instance 관계 보기 내장 변수를 이용해서 Class 와 Instance 관계를 확인
class A(object): def whoami(self): return self.__class__.__name__
a = A()
print a.whoami()print a.__class__.__base__.__name__
인스턴스의 클래스 이름: A
인스턴스의 클래스의 상속 클래스 이름: object
생성자와 소멸자
생성자 처리 구조파이썬은 생성자는 클래스이 __init__() 메소드를 binding 하여 처리
Instance = ClassA( 인자 ) ClassA.__init__(instance, 인자 )
ClassA( 상위클래스 ) : def __init__(self, 인자 ) : # 생성자로직
Source code Execute code
생성자 -Creating Instance 파이썬 생성자 __init__() 함수를 오버라이딩한 후클래스이름 ( 파라미터 ) 를 이용하여 객체 생성생성자 함수는 자동으로 연계됨
class Employee: 'Common base class for all employees' empCount = 0
def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1
"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)
생성자 정의
인스턴스 객체 생성생성자와 자동으로 연계
소멸자 - Destroying Objects클래스의 생성된 인스턴스를 삭제하는 메소드
#!/usr/bin/python
class Point: def __init( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "destroyed"
pt1 = Point()pt2 = pt1pt3 = pt1print id(pt1), id(pt2), id(pt3) # prints the ids of the obejctsdel pt1del pt2del pt3
소멸자 정의
소멸자 활용
Class decorator : 기본 생성자에서 함수 전달 , 인스턴스 호출에서 함수의 파라미터 전달 전달함수 실행시 생성자 실행 및 인스턴스 실행
# 테코레이터 클래스 정의하고 생성자에 전달class decoratorWithoutArguments(object): def __init__(self, f): print ("Inside __init__()") self.f = f
# 호출하는 곳에 내부함수 처리 로직 처리 def __call__(self, *args): print( "Inside __call__()") self.f(*args) print( "After self.f(*args)")
# 데코레이터 정의 및 전달함수 정의@decoratorWithoutArgumentsdef sayHello(a1, a2, a3, a4): print( 'sayHello arguments:', a1, a2, a3, a4)
데코레이터 클래스 정의 전달 함수 정의 함수 실행# 데코레이터 호출 print ("Preparing to call sayHello()")
sayHello("say", "hello", "argument", "list")
print ("After first sayHello() call")
sayHello("a", "different", "set of", "argu-ments")
print ("After second sayHello() call"))
메소드 접근자
Class 멤버 접근자 - cls클래스 객체의 변수나 메소드 접근을 위해 cls 키워드 사용
Instance 멤버 접근자 -self인스턴스객체 메소드의 첫 인자는 Self 를 사용하여 각 인스턴스별로 메소드를 호출하여 사용할 수 있도록 정의
Method- Instance클래스 객체에서 생성되는 모든 인스턴스 객체에서 활용되므로 클래스 이름공간에서 관리메소드 첫 파라미터에 self 라는 명칭을 정의
Method- 클래스 decorator클래스 객체에서 처리되는 메소드를 정의한다 . 클래스 메소드는 첫번째 파라미터에 cls 를 전달한다 .
장식자 @classmethod : 클래스 함수 위에 표시 -Python 2.x함수 classmethod() : 별도 문장으로 표시 – Python 3.x
인스턴스 객체도 호출이 가능
Method- 정적 decorator클래스 객체로 생성된 모든 인스턴스 객체가 공유하여 사용할 수 있다 .
장식자 @staticmethod : 정적함수 위에 표시 – Python 2.x함수 staticmethod() 는 별도의 문장으로 표시 – Python 3.x
정적메소드는 파라미터에 별도의 self, cls, 등 객체에 대한 참조값을 전달하지 않아도 됨 인스턴스 객체에서도 호출이 가능
Accessing Members클래스를 정의한 후에 인스턴스를 생성하고 메소드 호출 및 클래스 변수를 직접 호출하여 출력
class Employee: 'Common base class for all employees‘ empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.emp-Count def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
Class 정의# 인스턴스 객체 생성 : 생성자 호출emp1 = Employee("Zara", 2000) # 인스턴스 메소드 호출emp1.displayEmployee()
# 인스턴스 객체 생성 : 생성자 호출emp2 = Employee("Manni", 5000) # 인스턴스 메소드 호출emp2.displayEmployee()
# 클래스 변수 호출 및 출력print "Total Employee %d" % Employee.empCount
Instance 생성 및 호출
Method Bound/unbound(1)클래스이름과 인스턴스이름으로 메소드를 호출하면 bounding 처리 됨메소드 선언시 인자로 self, cls 를 정의되어 있음
>>> class Preson() :... def printP(self) :... print(' instance method ')... def printC(cls) :... print(' class method')… >>> p = Preson() # 인스턴스 생성>>> p.printP() # 인스턴스 메소드 bounding instance method >>> Preson.printP(p) # 인스턴스 메소드 unbounding instance method >>>
인스턴스를 생성하고 인스턴스 메소드 호출시는 bounding 처리 클래스로 인스턴스 메소드 호출시는 인자로 인스턴스 객체를 전달해서 unbounding
Method Bound/unbound(2)메소드 선언시 인자로 self, cls 를 정의되어 있는 것에 따라 매칭시켜야 됨
Transformation Called from an Object Called from a Class
Instance method f(*args) f(obj,*args)
Static method f(*args) f(*args)
Class method f(cls, *args) f(*args)
Class Inheritance
Inheritance상속은 상위 클래스를 하나 또는 여러 개를 사용하는 방법 class 상위 클래스명 : pass class 클래스명 ( 상위 클래스명 ) : pass
상속 정의시 파라미터로 상위 클래스명을 여러 개 작성시 멀티 상속이 가능함 class 클래스명 ( 상위 클래스명 , 상위 클래스명 ) : pass
Class 구조 클래스는 슈퍼클래스를 상속
Super ClassClass
상속
class A(object): def __init__(self) : self.instanceS = " static instance member" def whoami(self): return self.__class__.__name__
클래스 구조 예시 (1)>>> one = 1>>> type(one)<type 'int'>>>> type(type(one))<type 'type'>>>> type(one).__bases__(<type 'object'>,)>>> >>> object <type 'object'>>>> type <type 'type'> >>> type(object) <type 'type'>>>> object.__class__ <type 'type'>>>> object.__bases__ ()>>> type.__class__ <type 'type'>>>> type.__bases__ (<type 'object'>,)>>> isinstance(object, object) True>>> isinstance(type, object) True>>> isinstance(object, type)True
objecttype
int float str
클래스 구조
클래스 구조 예시 (2)
>>> list <type 'list'>>>> list.__class__ <type 'type'>>>> list.__bases__ (<type 'object'>,)>>> tuple.__class__, tuple.__bases__ (<type 'type'>, (<type 'object'>,))>>> dict.__class__, dict.__bases__ (<type 'type'>, (<type 'object'>,))>>>>>> mylist = [1,2,3] >>> mylist.__class__ <type 'list'>
데이터 타입은 상속을 받을 때 타입 객체를 바로 받지만 base 는 object 클래스를 처리 객체 생성 예시
메타클래스 클래스 인스턴스
type object
list mylist
Inheritance- scope
상속된 클래스도 검색하는 순서가 파라미터를 정리한 순서대로 변수나 메소드를 검색하여 처리됨상속된 클래스에 동일한 이름이 변수나 메소드가 존재시 첫번째 검색된 것으로 처리함class 클래스명 ( 상위 클래스명 , 상위 클래스명 ) : pass
Inheritance - 예시
class Parent: # define parent class parentAttr = 100 def __init__(self): print "Calling parent constructor“ def parentMethod(self): print 'Calling parent method' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Parent attribute :", Parent.parentAttr
class Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method'
c = Child() # instance of childc.childMethod() # child calls its method c.-parentMethod() # calls parent's method c.se-tAttr(200) # again call parent's method c.getAttr() # again call parent's method
# 결과값Calling child constructor Calling child method Calling parent method Parent attribute : 200
Class 정의 인스턴스 생성 및 호출
Mixin기존 상속구조에 대한 변경을 최소화하기 위해 메소드기반의 클래스 생성하여 상속받아 처리하는 방법
class Mixin : def add(self,x,y) : return self.x + self.y def sub(self,x,y) : if isinstance(self, String) : return " String no support" else : return self.x - self.y
class Number(Mixin) : def __init__(self, x,y) : self.x = x self.y = y
class String(Mixin) : def __init__(self, x,y) : self.x = x self.y = y
n1 = Number(5,6)n1.add(n1.x,n1.y)n1.sub(n1.x,n1.y)
s1 = String("hello ", "world")print s1.add(s1.x, s1.y)print s1.sub(s1.x, s1.y)
인스턴스 생성 및 호출
상속구조 확인하기
Method resolution orderMro 메소드는 type 클래스에 있으므로 직접 type.mro(class) 로 호출 가능
class A(object) : def __init__(self,name) : self.name = name a = A('dahl')print a.name
print(type.mro(A))print(type(a),type(a).mro())
# 실행 결과dahl[<class '__main__.A'>, <type 'object'>](<class '__main__.A'>, [<class '__main__.A'>, <type 'object'>])
MRO 처리 시 오류Old style 로 정의시 type class 를 알 수 없으므로 mro 를 사용하려면 명확히 상속을 표시해야 함
class test1 : print " test1 “
print test1.mro()
# 실행 결과AttributeError: class test1 has no attribute 'mro'
class test1(object) : print " test1 "
print test1.mro()
# 실행 결과 test1 [<class '__main__.test1'>, <type 'object'>]'
상속 : __mro__, mro()상속인 경우 클래스 객체들이 우선순서를 확인하는 속성과 메소드
class Base1(object): def amethod(self): print "Base1"
class Base2(Base1): pass
class Base3(object): def amethod(self): print "Base3"
class test(Base2,Base3) : A = 'aaaa‘
instance = test() instance.amethod() print test.__mro__ print test.mro()
# 실행 결과Base1(<class '__main__.test'>, <class '__main__.Base2'>, <class '__main__.Base1'>, <class '__main__.Base3'>, <type 'object'>)[<class '__main__.test'>, <class '__main__.Base2'>, <class '__main__.Base1'>, <class '__main__.Base3'>, <type 'object'>]
자기 메소드 호출하기
Hasattr 메소드 재작성 후 확인상속인 경우 클래스 객체들이 우선순서를 확인하고 속성을 접근하는 예시
class A(object) : def __init__(self,name) : self.name = name def hasattr(self, attrname): if hasattr(self,attrname) : val = "B“ # 최상위 if attrname in A.__dict__ : val = "A“ # 클래스 if attrname in self.__dict__ : val = "S“ # 인스턴스 else : val = "N" return val
# 실행 결과TrueTrueTrueB SA
a = A("dahl")
print hasattr(a,"name")print hasattr(a,"__str__")print hasattr(object,"__str__")print a.hasattr("__str__")print a.hasattr("name")print a.hasattr("__init__")
Super() 사용하기
Super() 함수 (2.x)Super( 클래스 , 서브클래스 또는 인스턴스 )Class 변수를 호출하였지만 mro() 순성 따라 A.bar 가 호출되어 처리됨
class A(object) : bar = 100 def foo(self) : pass class B(object) : bar = 0 class C(A,B) : xyz = 'abc' print " super function ", super(C,C())
print C.mro()print super(C,C()).__self__print super(C,C()).barprint super(B,B()).__self__print super(B,B()).__self__.bar
# 실행 결과super function <super: <class 'C'>, <C object>>[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>]<__main__.C object at 0x0F01BA10>100 A.bar 의 값<__main__.B object at 0x0F01B6B0>0 B.bar 의 값
Super() 함수의 binding(2.x)Super( 클래스 , 인스턴스 ). 메소드 () 은 클래스 .메소드 ( 인스턴스 ) 로 연결되는 구조이므로 파라미터가 빠지면 binding 이 되지 않는다 .
print super(C) # 실행 결과<super: <class 'C'>, NULL>
print super(C).fooFoo 는 인스턴스 함수이라서 binding 에러# 실행 결과AttributeError: 'super' object has no attribute 'foo'
Super() 을 이용한 접근 (2.x)Super( 클래스 , 인스턴스 ) 객체에 __get__ 메소드가 구현되어 있어 재상속 후에 처리시 에러없이 상위 클래스를 접근 가능
class A(object) : bar = 100 def foo(self) : pass class B(object) : bar = 0 class C(A,B) : xyz = 'abc‘
class D(C) : sup = super(C) print D().supprint D().sup.fooprint super(C,D()).fooprint D().sup.bar
# 실행 결과<super: <class 'C'>, <D object>><bound method D.foo of <__main__.D object at 0x0F01BF90>><bound method D.foo of <__main__.D object at 0x0F01BF90>>100
D().sup 일때 상위 클래스 C 와 하위 인스턴스 D() 가 있어 매핑되어 처리 가능D().sup.foo == Super(C,D()).foo 로 바인딩한 것과 같다
Super(C).__get__(D(), ‘foo’) 처럼 인식
Super() 함수 (3.x)파이썬 3.x 버전부터 super() 함수이 파라미터가 없어도 자동으로 스택프레임에서 검색하여 처리함
Overriding
Overriding메소드를 이름으로 검색하므로 하위 클래스에 동일한 메소드가 존재하면 인스턴스 호출시 하위 클래스 메소드 부터 호출하므로 Overriding 처리 class 상위 클래스명 : def method(self) : pass class 클래스명 ( 상위 클래스명 ) : def method(self) : pass
Overriding 구조 동일한 메소드를 instance/Class/Super Class 에 다 정의할 경우 실행시 instance 부터 호출이 되는 구조
Super ClassClassinstance
상속인스턴스화
클래스 정의 시 메소드클래스 정의 시 슈퍼 클래스메소드 재정의Runtime 시 클래스 및 슈퍼클래스 메소드 정의
Overriding 발생 Overriding 발생
연산자 Overriding 예시Super ClassClassinstance
상속인스턴스화
Overriding 발생
class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b)
# __init__ 생성자 메소드 overridingv1 = Vector(2,10) v2 = Vector(5,-2)
# __add__ 메소드 overriding print v1 + v2
# __str__ 메소드 overriding print v1
__getattr__/__setattr__ 메소드인스턴스에서 상속된 부모 클래스의 속성을 조회 및 갱신이 가능
>>> dir(dict)['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', ….']>>>
dict 클래스에서 보관하는 속성을 조회
>>> # dict 인스턴스 생성하고 dict 내 >>> # 매소드 호출>>> d = {'a': 1}>>> d.__getattribute__('__class__')<type 'dict'>>>>
dict 클래스의 인스턴스로 클래스 내부의 속성을 조회
./[] 연사자 overriding다른 클래스를 만들어서 연산자를 다양하게 사용하기 위해 오버라이딩 처리
class Test1(dict) : def __getattr__(self,name) : return self[name] def __setattr__(self,name, value) : self[name] = value
t1 = Test1()t1.a= 10t1['btest'] = 100
print t1.aprint t1['btest']print t1.__dict__print t1
# 결과값10100{}{'a': 10, 'btest': 100}
Super Class
Classinstance
상속인스턴스화
Overriding 발생
./[] 연사자 overriding - 설명부모 클래스의 메소드를 재정의해서 현재 클래스의 메소드가 호출되도록 처리
class Test1(dict) :
def __getattr__(self,name) : return self[name]
def __setattr__(self,name, value) : self[name] = value
1. dict 클래스의 __getattr__, __setattr__ 메소드에 대한 오버라이딩 처리
2. dict 타입이라서 실제 self 내부 데이터 타입에 저장됨
인스턴스 생성 기초
Instance 구조 클래스는 슈퍼클래스를 상속하고 인스턴스를 만들어서 실제 기능들을 동작시킨다 .
Super ClassClassinstance
상속인스턴스화
Instance 생성 방식 클래스명에 파라미터에 인스턴스 변수값을 정의해서 인스턴스를 생성함 인스턴스 생성시 생성자가 호출되어 처리됨
변수명 = 클래스명 ( 인스턴스 변수값 , 인스턴스 변수값 )def __init__(self, 인스턴스 변수값 , 인스턴스 변수값 ) : self. 인스턴스 변수 = 인스턴스변수값 매칭호출시 매칭됨
Instance 생성 예시 Class 키워드로 클래스 정의 상속은 class 키워드 다음 () 내에 상속할 클래스 정의 인스턴스 생성은 클래스명에 () 연산자 사용
Super ClassClassinstance
상속인스턴스화
class A(object): def whoami(self): return self.__class__.__name__
a = A()
Instance Scope 객체들간의 관계 ( 상속 및 instance 생성 등 ) 에 따라 객체 멤버들에 대한 접근을 처리검색 순서 : 인스턴스 > 클래스 > 상속클래스 >builtin Class
상속이 많아지면 다양한 상위 멤버들을 접근하여 처리할 수 있다 .
Predefined Instance Attributes
Attribute Type Read/Write Description__dict__ dictionary R/W The instance name space__class__ class R/W The class of this instance
클래스와 인스턴스 접근
Members( 변수 ) AccessClass/Instance 객체에 생성된 변수에 대한 구조 및 접근 방법
>>> # class 정의 >>> class C(object): ... classattr = "attr on class“... >>> # 객체 생성 후 멤버 접근>>> cobj = C() >>> cobj.instattr = "attr on instance" >>> >>> cobj.instattr 'attr on instance' >>> cobj.classattr 'attr on class‘
멤버접근연사자 (.) 를 이용하여 접근
C
classattr
cobj:C
instattr
cobj = C()
Members( 변수 ) Access - 세부Class/Instance 객체는 내장 __dict__ 멤버 ( 변수 )에 내부 정의 멤버들을 관리함
>>> # 내장 __dict__ 를 이용한 멤버 접근 >>> # Class 멤버>>> C.__dict__['classattr'] 'attr on class' >>> # Instance 멤버>>> cobj.__dict__['instattr'] 'attr on instance' >>>>>> C.__dict__ {'classattr': 'attr on class', '__module__': '__main__', '__doc__': None}>>>>>>>>> cobj.__dict__ {'instattr': 'attr on instance'} >>>
C
cobj:C
cobj = C()
__dict__:dict
classattr
__dict__:dict
classattr
내장 객체
내장 객체
Members( 메소드 ) AccessClass 정의시 인스턴스 메소드 정의를 하면 Class 영역에 설정
>>> #Class 생성>>> class C(object): ... classattr = "attr on class“... def f(self):... return "function f" ... >>> # 객체 생성>>> cobj = C() >>> # 변수 비교>>> cobj.classattr is C.__dict__['classattr'] True
변수 비교
C
classattr
f
cobj:C
instattr
cobj = C()
Members( 메소드 ) Access- 세부인스턴스에서 인스턴스메소드 호출하면 실제 인스턴스 메소드 실행환경은 인스턴스에 생성되어 처리
>>> # 인스턴스에서 실행될 때 바운드 영역이 다름>>> # is 연산자는 동일 객체 체계>>> cobj.f is C.__dict__['f'] False >>>>>> C.__dict__ {'classattr': 'attr on class', '__mod-ule__': '__main__', '__doc__': None, 'f': <function f at 0x008F6B70>} >>> 인스턴스에 수행되는 메소드 주소가 다름>>> cobj.f <bound method C.f of <__main__.C instance at 0x008F9850>> >>> # 인스턴스 메소드는 별도의 영역에 만들어짐>>> # 인스턴스 내에 생성된 메소드를 검색>>> C.__dict__['f'].__get__(cobj, C) <bound method C.f of <__main__.C instance at 0x008F9850>>
C
cobj:C
cobj = C()
__dict__:dict
classattr
f
__dict__:dict
classattr
f
내장 객체
내장 객체
Controlling Attribute AccessInstance 의 Attribute 에 대한 접근을 할 수 있는 내부 함수__getattr__(self, name)__setattr__(self, name, value)__delattr__(self, name)__getattribute__(self, name)
Controlling Attribute Access인스턴스의 속성에 대한 접근을 내부 함수로 구현하여 접근
class A() : __slots__ =['person_id', 'name'] def __init__(self, person_id, name) : self.person_id = person_id self.name = name def __getattr__(self, name) : return self.__dict__[name] def __setattr__(self, name, value): if name in A.__slots__ : self.__dict__[name] = value else: raise Exception(" no match attribute") def __delattr__(self, name) : del self.__dict__[name]
def __getattribute__(self, name): return self.__dict__[name]
a = A(1,'dahl')
print a.__getattr__('name')print a.__getattr__('person_id')
print a.__dict__
print a.__setattr__('name','moon')print a.__setattr__('person_id',2)
print a.__getattr__('name')print a.__getattr__('person_id')
print a.__delattr__('name')print a.__dict__
a.name = 'gahl'
#a.s = 1
print a.__dict__
Association
Association객체간에 관계를 구성하여 처리객체내부에 관계 객체를 생성하여 해당 객체의 기능을 처리
AB
Association객체간에 관계를 구성하여 처리객체내부에 관계 객체를 생성하여 해당 객체의 기능을 처리
Association객체간에 관계를 구성하여 처리객체내부에 관계 객체를 생성하여 해당 객체의 기능을 처리
Composition is an Association
Aggregation is an Association
Composition is a strong Association (If the life of contained object totally depends on the container object, it is called strong associa-tion)
Aggregation is a weak Association (If the life of contained object doesn't depends on the container object, it is called weak associa-tion)
Association:Object Chain
#class 정의하고 인스턴스에서 타 객체를 호출class A: def __init__(self ): print 'a' self.b = B()
#object chain 을 하는 class 생성class B: def __init__(self ): print 'b' def bbb(self): print "B instance method " a = A()
print a.b.bbb()
객체들간의 연결고리 (Association, Composite 관계 ) 가 있을 경우 메소드 결과값을 객체로 받아 연속적으로 실행하도록 처리
객체 . 내부객체 .메소드 처리# 결과값abB instance method None
Association: 작성 예시
# association 클래스 정의class Other(object):
def override(self): print "OTHER override()"
def implicit(self): print "OTHER implicit()"
def altered(self): print "OTHER altered()"
객체관의 관계가 상속이 아닌 사용관계 (use) 로 전환# 사용 클래 스 정의class Child(object):
def __init__(self): # 인스턴스 생성시 속성으로 정이 self.other = Other()
def implicit(self): self.other.implicit()
def override(self): print "CHILD override()"
def altered(self): print "CHILD, BEFORE OTHER al-tered()" self.other.altered() print "CHILD, AFTER OTHER altered()"
Dependency객체간에 관계를 구성하여 처리객체내부에 관계 객체로써 메소드 등에서 일회성으로 해당 객체를 생성하여 기능을 처리
AB
Dependency: Method Chain
class C: def __init__(self ): print 'a' self.b = B() def ccc(self, b) : return b.bbb()
#object chain 을 하는 class 생성class B: def __init__(self ): print 'b' def bbb(self): print "B instance method " a = C()
print a.b.bbb()
print a.ccc(B())
객체의 관계가 일회성 적으로 처리가 되는 관계
객체 . 메소드 (인스턴스객체 ) 처리# 결과값abB instance method NonebB instance method None
Self Method Chain
class Person: def name(self, value): self.name = value return self def age(self, value): self.age = value return self def introduce(self): print "Hello, my name is", self.name, "and I am", self.age, "years old."
person = Person() # 객체의 메소드를 연속적으로 호출하여 처리person.name("Peter").age(21).introduce()
객체 내의 메소드의 결과를 자기자신으로 리턴하여 메소드를 연속해 호출하여 처리
타 객체 Method Chain
class A: def __init__(self ): print 'a' self.b = B() class B: def __init__(self ): self.c = C() print 'b' def bbb(self): print "B instance method " return self.c class C: def __init__(self ): print 'c' def ccc(self): print "C instance method "
클래스 정의시 내부에서 인스턴스를 가진 경우 chain 처리를 위해 return 으로 해당 객체를 전달
# 결과값acbB instance method C instance method None
a = A()
print a.b.bbb().ccc()
Class 확인 방법
issubclass/isinstance 함수
>>> issubclass(list,object)True>>> list.__bases__(<type 'object'>,)>>> issubclass(list, type)False>>>
issubclass() : __bases__ 기준으로 상속관계 isinstance() : __ class__ 기준으로 인스턴스 객체 관계
>>> isinstance(list, type)True>>> list.__class__<type 'type'>>>> >>> isinstance(list, object)True>>>
issubclass 처리 isinstance 처리
Class & instance namespaceClass Object 는 클래스 메소드 , 정적메소드 , 클래스 내부 변수 등을 관리한다 .파이썬은 변수나 메소드 검색 기준이 인스턴스 > 클래스 > Built-in Class 순으로 매칭시키므로 . 연산자를 이용하여 인스턴스도 메소드 호출이 가능하다 .
>>> class Simple : ... pass... >>> Simple<class __main__.Simple at 0x0212B228>>>> Simple.__name__'Simple‘>>> Simple.__dict__{'__module__': '__main__', '__doc__': None}
>>> s = Simple()>>> s.__dict__{}>>> s.name = "Simple instance">>> s.__dict__{'name': 'Simple instance'}
Instance 생성 및 인스턴스 멤버 추가Class 정의
Descriptor Protocol
DescriptorDescriptor 는 특성 객체의 속성 접근시 먼저 그 속성의 특징을 체크하여 처리할 수 있는 방법으로기술자 프로토콜로 제지하면서 처리는 " 바인딩 행동 " 을 가진 메소드들로 구성 __get__(self, instance, owner),__set__(self, instance, value),__delete__(self, instance).
Descriptor 메소드 파라미터별도의 descriptor 와 실체 class 인스턴스 간의 실행환경을 연계하여 처리Self: decriptor 인스턴스Instance: 실체 class의 인스턴스Owner: 실체 class 의 타입Value : 실체 class의 인스턴스의 변수에 할당되는 값
__get__(self, instance, owner),__set__(self, instance, value),__delete__(self, instance)
Descriptor 종류Method descriptor 와 Data descripter 로 구분
Method descriptor 는 __get__(self, instance, owner) 구현
Data descriptor 는 __get__(self, instance, owner) __set__(self,instance, value),
__delete__(self, instance) 구현
Descriptor : int.__add__ 예시Method descriptor 로 구현되어 __get__(self, instance, owner) 가지고 있다
P =1# 직접 호출p.__add__(3) # 결과값 4# 인스턴스에서 호출type(p).__add__.__get__(p,int)(3) # 결과값 4#class 에서 호출int.__add__.__get__(1,int)(3)
Descriptor : binding behavior
binding 하는 방법Direct Call
Instance Bind-ing
Class Binding
Super Binding
class D(object) : def __init__(self, x) : self.x = x def __get__(self,instance=None,cls=None) : return self.x class D1(D) : def __init__(self, x) : D.__init__(self,x)
d = D(1)print " d"print d.__dict__print d.xprint " direct call",d.__get__()print " Class binding call ",D.__get__(d,d)print "instance binding",type(d).__get__(d,d)d1 = D1(2)print " d1"print d1.__dict__print d1.xprint " direct call",d1.__get__()print " Class binding call ", D1.__get__(d1,d1)print "instance binding",type(d1).__get__(d1,d1)print D1.mro()print "super binding",super(D1,d1).__get__(d1,d1)
Basic data descriptorData Descriptor 클래스를 생성해서 처리하는 방법
class Descriptor(object): def __init__(self): self._name = '' def __get__(self, instance, owner): print "Getting: %s" % self._name return self._name def __set__(self, instance, name): print "Setting: %s" % name self._name = name.title() def __delete__(self, instance): print "Deleting: %s" %self._name del self._name
class Person(object): name = Descriptor()
>>> user = Person() >>> user.name = 'john smith' Setting: john smith >>> user.name Getting: John Smith 'John Smith‘>>> del user.name Deleting: John Smith
Creating Property- 객체 직접 정의 (1)
인스턴스 객체의 변수 접근을 메소드로 제약하기 위해서는 Property 객체로 인스턴스 객체의 변수를 Wrapping 해야 함property(fget=None, fset=None, fdel=None, doc=None)
class P:
def __init__(self,x): self.x = x def getx(self) : return self.x def setx(self, x) : self.x = x def delx(self) : del self.x
x = property(getx,setx,delx," property test ")
Getter, setter, deleter 메소드를 정의
인스턴스 객체의 변수명과 동일하게 Property 객체 생성 ( 내부에 _x 생김 )
Creating Property– 객체 직접 정의 (2)
실제 인스턴스 객체의 변수에 접근하면 Property 객체의 메소드를 호출하여 처리되고 인스턴스 객체의 변수값이 변경됨
p1 = P(1001)print id(p1.x)print P.__dict__['x']print id(p1.__dict__['x'])print p1.xp1.x = -12print p1.xprint p1.__dict__
# 처리결과값44625868<property object at 0x02C1D4E0>446258681001-12{'x': -12}
Creating Property decorator(1)
인스턴스 객체의 변수 접근을 메소드로 제약하기 위해서는 Property 객체로 인스턴스 객체의 변수를 Wrapping 해야 함property(fget=None, fset=None, fdel=None, doc=None)
class P:
def __init__(self,x): self.x = x @property def x(self): return self.__x @x.setter def x(self, x): self.__x = x @x.deleter def x(self): del self.x
Getter, setter, deleter 메소드를 정의인스턴스 객체의 변수명과 동일하게 Property 객체 생성 ( 내부에 _x 생김 )
Creating Property decorator(2)
Property 객체 생성하여 처리하는 방식과 동일
p1 = P(1001)print id(p1.x)print P.__dict__['x']print id(p1.__dict__['x'])print p1.xp1.x = -12print p1.xprint p1.__dict__
# 처리결과값44625916<property object at 0x02C1D3C0>446259161001-12{'x': -12}
내장함수를 통한 객체접근
Built-in 내장함수내장함수를 이용하여 객체의 속성에 대한 접근getattr(object, name[, default])setattr(object, name, value)delattr(object, name)hasattr(object, name)callable(object)
Built-in 내장함수 : 예시 1객체의 속성을 접근하고변경
class A(): def __init__(self, name,age) : self.name = name self.age = age a = A('dahl',50)
if hasattr(a,"name") : print getattr(a,"name") setattr(a,"name","Moon") print getattr(a,"name")else : pass
if hasattr(a,"age") : print getattr(a,"age")else : pass
# 처리결과값dahlMoon50
Built-in 내장함수 : 예시 2메소드 및 함수여부 확인 후 실행
class A(): def __init__(self, name,age) : self.name = name self.age = age def in_set(self,name,default) : self.__dict__[name] = default print self.__dict__[name]
a = A('dahl',50)
def add(x,y) : return x+y if callable(add) : add(5,6)else : pass
if callable(a.in_set) : a.in_set('age',20)else: pass
# 처리결과값dahlMoon5020
Information Hiding
Information hiding - 변수__ 명칭 : Private ( 객체 내부에서만 사용 ) 외부에서 호출시 mangling 되는 구조로 요청시 접근 가능 인스턴스 ._ 클래스명 __ 명칭_ 명칭 : protected ( 클래스 및 하위 클래스에서만 사용 )
Information hiding - 변수예시 명칭 : public (파이썬은 공개되는 게 기본 ) __명칭 : Private (객체 내부에서만 사용 ) mangling 되는 구조로 명칭이 변경됨 호출시는 인스턴스 ._클래스명__명칭 _명칭 : protected (클래스 및 하위 클래스에서만 사용권고 ) “don’t touch this, unless you’re a subclass”
>>>class foo: … def __secret(self): pass …
foo.__secret => AttributeError: __secret
>>>foo.__dict__{'_foo__secret': <function __secret at fc328>, '__module__': '__main__', '__doc__': None}
Private 메소드 정의 및 호출 Class Namespace 명칭
Information hiding – 변수 - 특별 __ 명칭 __ : 내장된 변수나 함수 등을 정의
Information hiding –Descriptor(Property)
파이썬은 Property 객체를 이용하여 객체내의 변수들의 접근을 메소드로 제어한다 .Descriptor 객체 , Property 객체나 @property decorator 를 이용인스턴스 객체의 변수 명과 동일한 property 객체가 생성되어야 함
Class P Instance p1{‘_x’: }
Descriptor 인스턴스 생성x
생성
인스턴스생성
class 내 descripter 인스턴스의 메소드 호출하여 처리
Instance p1p1.x 접근
Descriptor
Abstract Base Class
Abstract Class추상화 클래스란 직접 인스턴스를 만들지 못하고 상속을 받아 메소드 오버라이딩해서 사용하는 방식
Concrete Class instanceObj = ConcreteClass()
인스턴스 객체 생성
Abstract Class instanceObj = ConcreteClass()
인스턴스 객체 생성XAbstract
ClassConcrete
Class instance
ConcreteClass(Abstract Class)
상속
Obj = ConcreteClass()
인스턴스 객체 생성
Abstract Class 정의 방법추상화 클래스는 exception 및 abc 모듈 2 가지 처리 방법으로 만들 수 있다 .
exception 방식
abc 모듈 방식
모든 메소드를 subclass 에서 정의할 필요가 없다오류처리 : NotImplementedError
모든 메소드를 subclass 에서 정의해야 한다 . 오류처리 : TypeError
Abstract Class : exception 방식클래스 정의 후에 메소드 실행 부분을 exception 처리하고 상속받은 클래스에서 메소드 오버라이딩 처리
class Base: def foo(self): raise NotImplementedError("foo")
def bar(self): raise NotImplementedError("bar")
class Concrete(Base): def foo(self): return "foo() called"
상속 및 메소드 오버라이딩
추상클래스의 모든 메소드를 구현할 필요없음
Abstract Class : ABC 모듈ABC 모듈을 이용하여 정의해서 추상클래스 정의 후 상속을 받아 메소드 오버라이딩 처리
from abc import ABCMeta, abstractmethodclass Base(): __metaclass__=ABCMeta @abstractmethod def foo(self): pass @abstractmethod def bar(self): pass
class Concrete(Base): def foo(self): pass def bar(self): pass
상속 및 메소드 오버라이딩
추상클래스의 모든 메소드를 구현되어야 함
Abstract Class :property 정의Abstract Class 에서 decorator(@property) 를 사용하여 처리하기
class 구현클래스명 () : 변수명@propertydef get 메소드명 :@ 변수명 .setterdef set 메소드명 :@ 변수명 .deleterdef del 메소드명 :
import abcclass 추상클래스명 () : __metaclass__ = abc.ABCMeta
@abc.abstractpropertydef get 메소드명 :@ 변수명 .setterdef set 메소드명 :@ 변수명 .deleterdef del 메소드명 :
매칭
Abstract Class :property 구현Abstract Class 에서 decorator(@property) 를 사용하여 처리하기
import abc
class Base(object): __metaclass__ = abc.ABCMeta @abc.abstractproperty def value(self): return 'Should never see this' @value.setter def value(self, newvalue): return
class Implementation(Base): # private 처리 _value = 'Default value' @property def value(self): return self._value
@value.setter def value(self, newvalue): self._value = newvalue
abc 모듈을 이용해서 추상클래스 정의 추상클래스 상속받은 하위클래스 정의
Duck typing
Duck typeing 정의 방법다양한 클래스가 동일한 메소드를 처리할 수 있도록 인터페이스를 갖도록 만드는 법
함수
클래스
Duck typing 에 필요한 함수 정의 후 인스턴스들의 메소드 호출 처리
Duck typing 에 필요한 클래스 정의 후 인스턴스들의 메소드 호출 처리
Duck typeing : 함수 구현 (1)Duck typeing 함수 정의 후 클래스에 동일한 메소드 정의
def in_the_forest(duck): duck.quack() duck.feathers()
class Duck: def quack(self): print("Quaaaaaack!") def feathers(self): print("The duck has white and gray feathers.")
class Person: def quack(self): print("The person imitates a duck.") def feathers(self): print("The person takes a feather from the ground and shows it.") def name(self): print("John Smith")
함수 정의 클래스 정의
Duck typeing : 함수 구현 (2)Duck typeing 처리
def game(): donald = Duck() john = Person() in_the_forest(donald) in_the_forest(john)
print "function duck typeing "game()
# 실행 결과function duck typeing Quaaaaaack!The duck has white and gray feathers.The person imitates a duck.The person takes a feather from the ground and shows it.
Duck typeing : 클래스 구현 (1)
Duck typeing 클래스 정의 후 클래스에 동일한 메소드 정의
class InTheForest() : @staticmethod def quack(self) : self.quack() @staticmethod def feathers(self) : self.feathers() @classmethod def all(cls,self) : cls.quack(self) cls.feathers(self)
class Duck: def quack(self): print("Quaaaaaack!") def feathers(self): print("The duck has white and gray feathers.")
class Person: def quack(self): print("The person imitates a duck.") def feathers(self): print("The person takes a feather from the ground and shows it.") def name(self): print("John Smith")
함수 정의 클래스 정의
Duck typeing : 클래스 구현 (2)
Duck typeing 처리
def gameC(): donald = Duck() john = Person() InTheForest.all(donald) InTheForest.all(john)
print " class duck typeing "gameC()
# 실행 결과 class duck typeing Quaaaaaack!The duck has white and gray feathers.The person imitates a duck.The person takes a feather from the ground and shows it.
CLASS 로 RUNTIME클래스 생성
Moon Yong Joon
클래스 정의 하기
런타임 클래스 생성 정의다른 클래스를 __new__,__init__, type() 를 이용해서 새로운 클래스 생성
class ChattyType(type):
def __new__(cls, name, bases, dct): print( "Allocating memory for class", name) return type.__new__(cls, name, bases, dct)
def __init__(self, name, bases, dct): print ("Init'ing (configuring) class", name) super(ChattyType, self).__init__(name, bases, dct)
클래스를 메모리에 생성__new__ : 클래스 생성클래스 configure 처리__init__ : 초기화 생성
런타임 클래스 실행클래스와 메소드 함수를 정의
X = ChattyType('X',(),{'foo':lambda self:'foo'})
#Allocating memory for class X#Init'ing (configuring) class X
print(“XXXX”,X.__dict__)
print( X().foo())#(<class '__main__.X'>, 'foo')
# 처리결과<class '__main__.X'>foo
# 처리결과('XXXX', dict_proxy({'__dict__': <attribute '__dict__' of 'X' objects>, '__module__': '__main__', 'foo': <function <lambda> at 0x10577930>, '__weakref__': <attribute '__weakref__' of 'X' objects>, '__doc__': None}))
함수로 RUNTIME클래스 생성
Moon Yong Joon
사용자 정의 함수 사용
클래스 생성 함수 정의클래스와 메소드 함수를 정의
# 클래스에 등록할 메소드 정의def say_foo(self): print('foo')
# 클래스 생성 메소드 정의def class_with_method(func):
class klass: pass
# setattr(obj, name, value, /) # setattr(x, 'y', v) is equivalent to ``x.y = v'' setattr(klass, func.__name__, func)
return klass
클래스내의 속성을 등록 : Setattr( 클래스명 , 속성명 , 속성값 )
클래스 생성 함수 실행클래스 생성함수 파라미터에 메소드를 전달 한 후 실행
# 클래스 생성 Foo = class_with_method(say_foo)
print('Foo dict ', Foo.__dict__)
# 인스턴스 생성 및 메소드 호출foo = Foo()foo.say_foo()
# 클래스 __dict__ 출력 결과('Foo dict ', {'__module__': '__main__', 'say_foo': <function say_foo at 0x107071B0>, '__doc__': None})foo
#Foo.say_foo() 호출 처리 결과foo
Type 함수 사용 ( 변수 )
Type 함수 : 클래스 만들기 파이썬은 실제 리터럴 즉 값이 객체이므로 기본 객체의 구성을 이해해야
a =type('A',(object,),dict(a=1))
a.a # 1
Class A(object) : a = 1
과 동일한 표현
Type 함수 사용
클래스 생성 함수 정의클래스와 메소드 함수를 정의
# 생성자 및 세팅 메소드 추가def __init__(self, x=None): self._x = x
def set_x(self, value): self.x = value
#type 함수를 이용하여 클래스 정의SubClass = type('SubClass', (object,), { '__init__':__init__,'set_x': set_x})
Type( 클래스명 , 상속 ( 튜플 ),dict에 속성 추가 )
클래스 생성 함수 실행인스턴스를 생성해서 속성 세팅 실행
print(SubClass.__dict__)# 인스턴스 생성obj = SubClass()
# 속성세팅obj.set_x(42)
print( obj.x ) # Prints 42print (isinstance(obj, object) )
# 클래스 __dict__ 출력 결과{'set_x': <function set_x at 0x10577830>, '__module__': '__main__', '__dict__': <at-tribute '__dict__' of 'SubClass' objects>, '__weakref__': <attribute '__weakref__' of 'SubClass' objects>, '__doc__': None, '__init__': <function __init__ at 0x10707030>}
#obj.x 호출 처리 결과42#isinstance() 함수 처리결과True
Type 함수 사용 ( 상속 )
상속 클래스 정의 상속할 클래스 정의
# 상속될 클래스 정의class BaseClass(object) :
def __init__(self,x) : self.x = x
# 속성 ( 메소드 ) 정의def set_x(self, value): self.x = value
클래스 생성 실행클래스 생성 및 인스턴스 생성 후 실행
SubClass1 = type('SubClass', (BaseClass,), { 'set_x': set_x})
obj1 = SubClass1(5)
print(obj1.x)
obj1.set_x(50)
print(obj1.x)
# 처리결과#obj.x before5#obj.x after50
INSPECTMODULE
Insepect Module
Inspect modulemodule 에 대한 다양한 점검을 위한 함수를 제공
Function Description
inspect.getmoduleinfo(path)
모듈에 대한 정보를 가져오기ModuleInfo(name='in_test', suffix='.py', mode='U', module_type=1)
inspect.getmodulename(path) 모듈 네임만 문자열로 가져옴 in_test
inspect.ismodule(object) import 한 모듈을 확인 여부
Inspect class/object객체에 대한 다양한 점검을 위한 함수를 제공
Function Descriptioninspect.getmembers(object[, predi-
cate] 객체의 멤버를 튜플 ( 키와 값 ) 로 표시inspect.isclass(object) Object 에 클래스가 들어가면 True 이고 나머지는 False
inspect.ismethod(object) Object 가 메소드 여부 inspect.isabstract(object) Object 가 추상클래스 여부
inspect.ismethoddescriptor(object) int.__add__ 처럼 내장 메소드일 경우 descriptor protocol 존재해서 true 처리
inspect.isdatadescriptor(object) __get__, __set__, __delete__ 메소드를 가진 인스턴스일 경우 True
Inspect 함수함수에 대한 다양한 점검을 위한 함수를 제공
Function Descriptioninspect.isfunction(object) Object 가 함수 여부
inspect.isgeneratorfunction(object) Object 가 제너레이터 함수 여부inspect.isgenerator(object) Object 가 제너레이터 여부
함수클래스 확인Moon Yong Joon
함수 구조함수를 정의하면 function class 이 인스턴스가 생성된다 .
object
function codedef add(x,y) : return x+y
in-stance
함수 상속구조 확인하기add 함수를 기준으로 클래스 구조를 확인하면 최상위는 object 이고 function 과 code 클래스가 조회
object
function codedef add(x,y) : return x+y
instance
print add.__class__print type(add.func_code) print add.__class__.__bases__print add.func_code.__class__.__bases__
<type 'function'><type 'code'>(<type 'object'>,)(<type 'object'>,)