파이썬 중급: 클래스
- 클래스(Class)
클래스(Class)
1. 클래스(Class) 정의
- 클래스(Class)
- 객체 지향 프로그래밍(Object Oriented Programming, OOP)에서 특정 객체를 생성하기 위해 변수와 메서드를 정의하는 일종의 틀
- 내부적으로 객체를 정의하기 위한 상태 값을 의미하는 멤버 변수와 클래스의 동작인 메서드(함수)로 구성됨
- 기본 용어
- 클래스 객체(Class Object)
- class 정의문에 의해 지정된 문장들
- 인스턴스 객체를 만드는 틀을 역할을 함
- 메서드에 대한 모든 것을 보관함
- 인스턴스에서 메서드를 호출할 때 클래스의 메서드와 바인딩이 발생해서 처리되는 구조
- 인스턴스 객체(Instance Object)
- 클래스 객체에 의해 만들어진 객체
- __ init __ 메서드 내부에 지정된 속성을 가지는 네임스페이스만 있고 메서드는 클래스에 있는 것을 사용함
- 클래스 객체 멤버(Class Object Member)
- 클래스 속성, 클래스 메서드, 정적 메서드 등은 클래스가 직접 호출해서 처리할 수 있는 멤버
- 인스턴스는 자기 네임스페이스에 지정된 것을 빼면 모든 클래스 멤버에 인스턴스에서 직접 접근 가능
- 프로퍼티 속성: 메서드를 기반으로 이름으로 접근해서 처리되는 속성
- 인스턴스 객체 멤버(Instance Object Member)
- 인스턴스 속성만 인스턴스에서 관리하는 멤버
- 일반적인 인스턴스 메서드는 클래스 내에서 관리함
- 클래스 객체(Class Object)
1.1 객체의 분류
- 사물에는 기본 정보를 관리하는 클래스가 필요
class BookInfo : def init(self,title,author,date,publisher,page) : self.title = title self.author = author self.date = date self.publisher = publisher self.page = page
book1 = BookInfo(“서시”,”윤동주”,”1939”,”출판사”,100) book2 = BookInfo(“파이썬”,”달문”,”2017”,”출판사”,900)
import pprint pprint.pprint(book1.dict) pprint.pprint(book2.dict)
- 책에 대한 메타 정보인 범주 관리
class BookClass(BookInfo) : def init(self,title,author,date,publisher,page,isdn=None) : super().init(title,author,date,publisher,page) self.isdn = isdn
bookclass1 = BookClass(book1.__dict__,isdn=”1111111111111”) bookclass2 = BookClass(book2.dict,isdn=”2222222222222”)
import pprint pprint.pprint(bookclass1.dict) pprint.pprint(bookclass2.dict)
- 실제 만들어져 있는 객체로써 책을 관리
class BookInv(BookClass) : def init(self,title,author,date,publisher,page,isdn,inventno=None) : super().init(title,author,date,publisher,page,isdn) self.inventno = inventno
bookinv1 = BookInv(bookclass1.__dict__,inventno=3000) bookinv2 = BookInv(bookclass2.dict,inventno=3000)
import pprint pprint.pprint(bookinv1.dict) pprint.pprint(bookinv2.dict)
1.2 객체의 특징
- object 클래스로 객체의 레퍼런스 확인하기
a = object()
b = object()
print(a is b) print(id(a), id(b))
t = (1,2,3)
ts = tuple(t)
print(t is ts) print(id(t), id(ts))
- int 클래스에 대한 책임성 확인하기
a = int(10)
b = int(5)
print(a+b) print(a.add(b)) print(a-b) print(a.sub(b))
- int 클래스 내에서 관리하는 속성과 메소드 확인하기
for i,v in enumerate(dir(int),1) : print(v,end=” “) if i % 5 == 0 : print()
1.3 최상위 클래스 object 이해하기
- object 클래스 내부의 속성과 메소드 보기
for i,v in enumerate(dir(object),1) : print(v,end=” “) if i % 5 == 0 : print()
print(object.doc) print(object.name) print(object.str(object)) print(object.repr(object))
print(object.eq(object, object)) print(object is object)
o = object()
print(o) print(o.dict)
1.4 파이썬 클래스 생성 및 기본 상속 구조
1.4.1 클래스의 생성과 상속

- Type 클래스의 insetance 여부 확인
l = [type, object, int, float, str, tuple, list, dict,set]
for i in l : print(isinstance(i,type))
l = [type, object, int, float, str, tuple, list, dict,set]
for i in l : print(issubclass(i,object))
- Class 내부 속성 __ class __, __ bases __ 확인
l = [‘type’, ‘object’, ‘int’, ‘float’, ‘str’, ‘tuple’, ‘list’, ‘dict’,’set’]
for i in l : print(eval(i+”.class”))
l = [‘type’, ‘object’, ‘int’, ‘float’, ‘str’, ‘tuple’, ‘list’, ‘dict’,’set’]
for i in l : print(eval(i+”.bases”))
1.4.2 클래스와 인스턴스의 관계

- 내장 클래스와 인스턴스의 관계 확인
l = [‘object’, ‘int’, ‘float’, ‘str’, ‘tuple’, ‘list’, ‘dict’,’set’]
for i in l : print(eval(“isinstance(“+i+”(),”+i+”)”))
l = [‘object’, ‘int’, ‘float’, ‘str’, ‘tuple’, ‘list’, ‘dict’,’set’]
for i in l : print(eval(i+”().class”))
1.5 사용자 정의 클래스
- 사용자 정의 클래스 기본 확인
class Klass : pass
print(Klass.class) print(Klass.bases)
print(isinstance(Klass, type)) print(issubclass(Klass, object))
import pprint
class Int(int) : pass
a = Int(10) print(type(a),a)
pprint.pprint(Int.dict)
print(Int.class) print(Int.bases)
print(isinstance(Int, type)) print(issubclass(Int, object)) print(issubclass(Int, int))
- Person 사용자 클래스를 정의 및 속성 확인
class Person : def init(self, name, age) : self.name = name self.age = age
p = Person(“줄리아”,15)
print(p) print(p.dict) print(p.name) print(p.age)
o = set(dir(object)) pc = set(dir(Person))
print(pc-o)
print(Person.module) print(Person.bases) print(Person.class)
1.6 객체 네임스페이스 및 스코프
1.6.1 인스턴스와 클래스 객체 네임스페이스 및 스코프 처리 기준

- 클래스와 인스턴스 객체간의 네임스페이스 접근
class Klass : name = “Klass attr” def init(self, name) : self.name = name
def getname(self) :
return self.name
k = Klass(“instance attr”)
print(k.name) print(Klass.name)
k.getclassname = Klass.name print(k.dict) print(k.getclassname)
print(k.getname())
print(Klass.getname(k))
import pprint
pprint.pprint(Klass.dict)
print(k.getname) print(Klass.getname)
2. 생성자(Constructor)와 소멸자(Destructor)
2.1 생성자 이해하기: __ new __
- 클래스 생성자로 인스턴스 생성하기
import pprint
class AAA : def new(cls) : return object.new(cls)
aaa = AAA()
print(aaa)
pprint.pprint(AAA.dict)
print(isinstance(aaa,AAA))
- 자기 자신의 클래스만 처리
class OnlyKlass : def new(cls) : return cls
ok = OnlyKlass()
print(ok)
print(type(ok)) print(ok is OnlyKlass)
class OnlyKlass : def new(cls) : return cls
@classmethod
def getname(cls) :
return cls.name
@classmethod
def setname(cls, name) :
cls.name = name
import pprint
pprint.pprint(OnlyKlass.dict)
ok = OnlyKlass()
ok.setname(“ class method “) print(ok.getname())
2.2 초기화 메서드 사용하기: __ init __
- 인스턴스 속성을 초기화
class Pass : pass
p = Pass()
print(p.dict)
p.name = “양영초” p.age = 10
print(p.dict)
class INIT : count = 0 def init(self,name,age) : self.name = name self.age = age self.count += 1
i = INIT()
class INIT : count = 0 def init(self,name,age) : self.name = name self.age = age self.count += 1
i = INIT(“양영중”,15) print(i.dict)
print(i.name) print(i.age) print(i.count)
2.3 소멸자 메서드 사용하기: __ del __
- 소멸자 정의된 클래스 생성하기
class Counter : count = 0
def __init__(self,name) :
self.name = name
Counter.count = Counter.count +1
def __del__(self) :
Counter.count = Counter.count -1
x = Counter(“ First “) print(x) print(x.dict) print(Counter.count) y = Counter(“ Second “) print(y) print(y.dict) print(Counter.count)
del y print(Counter.count)
- 약한 참조 이용하기
a = 1 print(id(a)) b = a print(id(b))
del a print(b)
import weakref import gc
class MyObject(object): def my_method(self): print(‘my_method was called!’)
obj = MyObject()
r = weakref.ref(obj) print(type(r), r) s = r() assert isinstance(obj, MyObject) assert s is obj
s.my_method()
obj = 1 gc.collect() print(r) print(s) assert r() is not None
del s assert r() is not None
2.4 생성자 작동 원리 이해하기
- 생성자, 초기화, 호출연산자를 정의한 클래스
class MDPerson(object) : def new(cls,name,major) : return object.new(cls)
def __init__(self,name, major) :
self.name = name
self.major = major
def __call__(cls, name, major) :
print(" __new__ ")
self = cls.__new__(cls,name,major)
print(" __init__ ")
self.__init__(name,major)
return self
mdp = MDPerson.call(MDPerson,”이주원”,”quant”)
print(mdp) print(mdp.name) print(mdp.major)
mdp2 = type.call(MDPerson,”이주튜”,”quant”)
print(mdp2) print(mdp2.name) print(mdp2.major)
mdp3 = MDPerson(“이주하”,”quant”)
print(mdp3) print(mdp3.name) print(mdp3.major)
2.5 함수를 이용한 생성자 패턴
- 함수의 결과로 인스턴스 생성하기
class Person : def init(self,name,age) : self.name = name self.age = age
class Employee(Person): def init(self, name, age, depart,salary) : super().init(name,age) self.depart = depart self.salary = salary
class Employer(Person) : def init(self, name, age, salary) : super().init(name,age) self.salary = salary
def employ(name,age, *,depart=None,salary=None) : if depart is None : return Employer(name,age,salary=salary) else :
if salary == None :
salary = 0
return Employee(name,age,depart=depart,salary=salary)
e = employ(“정찬혁”,31,depart=”빅데이터부”,salary=30000)
print(e) print(type(e))
e = employ(“달문”,52,salary=300000)
print(e) print(type(e))
2.6 인스턴스 네임스페이스 변경하기: __ slots __
- __ slots __ 사용하기
class Klass : slots = (“name”,) def init(self, name,age) : self.name = name self.age = age
k = Klass(“name”,”age”)
class Klass : slots = (“name”,) def init(self, name) : self.name = name
k = Klass(“name”) print(k)
print(k.name) print(k.dict)
import pprint
pprint.pprint(dir(Klass))
print(Klass.slots) print(Klass.dict[Klass.slots[0]])
print(type(Klass.name))
k.name = “가을이” print(k.name)
Klass.age = 100
k.age
k.job = “Data Engineer”
- 관행적으로 __ dict __ 속성 조회 로직이 있을 경우
class MyClass : slots = [‘x’,’y’,’dict’]
def __init__(self,x,y) :
self.x = x
self.y = y
self.__dict__ = {}
m = MyClass(5,5) print(m.x, m.y) print(m.dict)
m.dict[‘a’] = 100
print(m.a)
m.b = 100
print(m.dict)
print(type(m), m.slots)
3. 객체 접근 연산(.)
3.1 점(dot) 연산
- 초기화 처리할 때 속성을 접근
class Person :
def __init__(self, name, age) :
self.name = name
self.age = age
def __setattr__(self, name, value) :
print(" __setattr__ ", name)
self.__dict__[name] = value
p = Person(“사람”, 50)
3.2 점 연산자 스페셜 메서드(Special Method) 기본 이해하기
- __ getattribute __를 이용해서 클래스 내부 검색
class Person :
job = "즐기기"
def __init__(self, name, age) :
self.name = name
self.age = age
def __getattribute__(self, name) :
print(" attribute name ", name)
return super().__getattribute__(name)
def __getattr__(self, name) :
print(" attr name ", name)
return Person.__dict__[name]
p = Person(“긍정”,55) print(p.name)
p.job
p.getattr(‘job’)
- attrgetter를 이용해서 속성 접근
class Person :
job = "즐기기"
def __init__(self, name, age) :
self.name = name
self.age = age
import operator
getname = operator.attrgetter(“name”,”age”,”job”)
p = Person(“가을이”,10)
print(getname)
print(getname(p))
4. 메서드 확인하기
4.1 메소드(Method) 이해하기
4.1.1 인스턴스 메서드(instance method) 확인
- 인스턴스 메소드 정의하기
class Klass_ins : def set(self,name,value) : setattr(self,name,value)
ki = Klass_ins() print(ki) print(isinstance(ki, Klass_ins))
ki.set(“name”,”강감찬”) ki.set(“age”,45)
print(ki.dict)
class Person : def init(self,name,age) : self.name = name self.age = age
p = Person(“서희”,35) print(p.dict)
4,1,2 클래스 메서드 정의
- 클래스 메서드 정의하기
class Klass_cls : @classmethod def set(cls,name,value) : setattr(cls,name,value)
Klass_cls.set(“name”,”클래스”) Klass_cls.set(“age”,50)
import pprint
pprint.pprint(Klass_cls.dict)
class Person : name = “” age = 0
@classmethod
def set(cls,name,value) :
setattr(cls,name,value)
@classmethod
def get(cls) :
return cls.name, cls.age
Person.set(“name”,”클래스”) Person.set(“age”,50)
print(Person.get())
p = Person() print(p.get()) print(p.name)
c = Person() c.name = “가을이” c.age = 55 print(c.get()) print(c.name) print(c.dict)
4.1.3 정적 메서드 정의
- 정적 메소드 정의하기
class Klass_st : name = “” age = 0 def init(self,name,age) : self.name = name self.age = age
@classmethod
def set(cls,name,value) :
setattr(cls,name,value)
@staticmethod
def get(obj) :
return obj.name, obj.age
import pprint
pprint.pprint(Klass_st.dict)
c = Klass_st(“인스턴스”,50)
Klass_st.set(“name”,”클래스”) Klass_st.set(“age”,55)
print(c.get(c)) print(Klass_st.get(Klass_st))
4.2 self / cls 매개변수 이해하기
4.2.1 인스턴스 메서드 정의 이해하기
- 인스턴스 메소드 self 알아보기
class InsKlass : def init(self,name) : self.name = name
def getname(self) :
return self.name
print(InsKlass.getname)
ins = InsKlass(“인스턴스”) print(ins.getname)
s = set(dir(InsKlass.getname))
i = set(dir(ins.getname))
print(i - s) print(ins) print(ins.getname.self) print(InsKlass.getname) print(ins.getname.func)
4.2.2 클래스 메서드 내부 확인하기
- 클래스 메소드 cls 알아보기
class ClsKlass : name = “클래스” def init(self,name) : self.name = name @classmethod def getname(cls) : return cls.name
a = ClsKlass(“인스턴스”)
print(ClsKlass.getname)
s = set(dir(ClsKlass.init))
c = set(dir(ClsKlass.getname))
print(c-s)
print(ClsKlass) print(ClsKlass.getname.self) print(ClsKlass.getname.func)
4.2.3 인스턴스 메서드의 self 매개변수 위치 이해하기
- self 변수를 미지정해서 인스턴스 메소드 알아보기
class Self : attr = (“name”,”age”) def init(*args) : print(“self argument “,args[0]) print(“self attribute “,args[0].init.self)
for i in range(1,len(args)) :
args[0].__dict__[Self.attr[i-1]] = args[i]
def get(*args) :
print("__self__ attribute ",args[0].get.__self__)
return args[0].name, args[0].age
s = Self(“Dahl”,22) print(s.dict) print(s)
print(s.get())
class Self_ :
def __init__(self,name,age) :
self.name = name
self.age = age
def get(self) :
return self.name, self.age
s = Self_(“Dahl”,22) print(s.dict) print(s) print(s.get())
4.3 외부 함수와 메서드를 동시에 사용하는 패턴 이해하기
4.3.1 외부 함수를 내부 인스턴스 메서드로 사용하기
- 외부 함수를 정의하고 클래스 내부에 할당하기
def getname(self) : return self.name
def getage(self) : return self.age
class Person : def init(self,name,age) : self.name = name self.age = age
getname = getname
getage = getage
p = Person(“함수”,44)
print(p.getname()) print(getname(p)) print(p.getage()) print(getage(p))
print(p.getname) print(getname) print(p.getname.func is getname) print(p.getage) print(getage) print(p.getage.func is getage)
- __ init __ 를 함수로 정의하고 클래스 내에 할당할 경우
def init(self,name,age) : self.name = name self.age = age
class Person : init = init
p = Person(“DahlMoon”,22) print(p.dict)
print(p.init.func) print(init)
4.4 플루언트 인터페이스(Fluent Interface, $→$ 메서드 체이닝)
- Method Chain 처리
class MethodChain : def init(self, content) : self.content = content
def intent(self,space) :
self.content = " "*space + self.content
return self
def suffix(self,content) :
self.content = self.content + "-" + content
return self
m = MethodChain(“하늘과별과 시”).intent(5).suffix(“윤동주”).content
print(m)
5. 캡슐화(Encapsulation)
5.1 내부 속성이나 메서드 명명 규칙 관행
5.2 보호된 이름: _이름
5.2.1 메서드로 보호 속성 감추기
- 보호된 이름 사용
class Protected : def init(self,name,age) : self._set(name,age)
def _set(self,name,age) :
self._name = name
self._age = age
def getname(self) :
return self._name
def getage(self) :
return self._age
p = Protected(“정찬혁”, 31)
print(p.dict)
print(p.getname()) print(p.getage())
print(p._name) print(p._age)
5.3 맹글링(Mangling)을 이용한 정보 은닉
- 속성이나 메소드에 대한 맹글링 처리
class Mangling : def init(self,name,age) : self.__set(name,age)
def __set(self,name,age) :
self.__name = name
self.__age = age
def getname(self) :
return self.__name
def getage(self) :
return self.__age
p = Mangling(“정찬혁”, 31)
print(p.dict)
print(p.getname()) print(p.getage())
print(p.__name) print(p.__age)
print(p._Mangling__name) print(p._Mangling__age)
import pprint
pprint.pprint(Mangling.dict)
p.__set(“맹글링”,55)
p._Mangling__set(“맹글링”,55)
print(p._Mangling__name) print(p._Mangling__age)
5.4 Property를 이용한 정보 은닉
- 프로퍼티로 속성을 숨기기
class PropertyClass : def init(self,name) : self._name = name @property def name(self) : return self._name @name.setter def name(self,value) : self._name = value
import pprint
pprint.pprint(PropertyClass.dict)
p = PropertyClass(“은옥주”)
print(p.name)
p.name = “금옥주” print(p.name)
print(p.dict) print(p._name) p._name = “동옥주” print(p.name)
6. 상속(Inheritance)
6.1 상속
6.1.1 상속 시 초기화 메서드 처리
- 부모 클래스의 초기화 모듈을 이용
class Parent : def init(self,name,age) : self.name = name self.age = age
class Child(Parent) : pass
import pprint
pprint.pprint(Parent.dict)
import pprint
pprint.pprint(Child.dict)
c = Child(“자식”,33) print(c) print(c.dict)
6.1.2 Super class와 sub class 관계 이해하기
- 상속관계 확인하기
class GrandParent : def init(self,name,age) : self.name = name self.age = age
class Parent(GrandParent) : pass
class Child(Parent) : pass
print(GrandParent.bases) print(Parent.bases) print(Child.bases)
print(issubclass(Parent, GrandParent)) print(issubclass(Child, Parent)) print(issubclass(Child, GrandParent))
6.1.3 상속에 따른 네임스페이스 검색
- 상속에 따른 네임스페이스 검색
class A : A_cls = “A 클래스 속성”
class B(A) : pass
class C(A) : pass
print(B.A_cls) print(C.A_cls)
B.A_cls = “B 클래스 속성”
print(B.A_cls) print(C.A_cls)
import pprint
pprint.pprint(A.dict)
import pprint
pprint.pprint(B.dict)
6.2 상속할 때 자식 클래스 초기화 기능 추가
- __ init_subclass __ 클래스 메소드
help(object.init_subclass)
class Super : def init_subclass(cls,name) : print(type(cls),cls) cls.name = name
class Sub(Super, name=”sub”) : pass
print(Sub.name)
import pprint
pprint.pprint(Super.dict)
import pprint
pprint.pprint(Sub.dict)
6.3 다중 상속(Multiple Inheritance)
6.3.1 다중상속 클래스 읽는 순서
- 다중 상속 Class 정의 및 읽는 순서 확인하기
class Parent1 : def init(self,name) : print(“ Parent1 “) self.name = name
class Parent2 : def init(self,name) : print(“ Parent2 “) self.name = name
class Child(Parent1, Parent2) : pass
import pprint
pprint.pprint(Child.mro())
c = Child(“다중상속”)
- 다른 부모 클래스의 __ init __ 메소드를 사용하고 싶을 경우
class Parent1 : def init(self,name) : print(“ Parent1 “) self.name = name
class Parent2 : def init(self,name,age) : print(“ Parent2 “) self.name = name self.age = age
class Child2(Parent1, Parent2) :
def __init__(self,name, age=None) :
if age is None :
super().__init__(name)
else :
Parent2.__init__(self,name,age)
c1 = Child2(“다중상속”) print(c1.dict)
c2 = Child2(“다중상속”, 33) print(c2.dict)
6.4 super 클래스 이해하기
- super 클래스 이해하기
class A : A_cls = “ AAA “
class B(A) : A_cls = “ BBB “
print(super(B,B()).A_cls)
class A : def init(self,name) : self.name = name
class B(A) : def init(self,name,age) : super().init(name) self.age = age
b = B(“슈퍼우먼”, 33) print(b.dict)
class A : def init(self,name) : self.name = name
class B : def init(self,name,age) : self.name = name self.age = age
class C(A,B) : def init(self,name,age=None) : super().init(name) if age : C.mro()[2].init(self,name,age)
c = C(“슈퍼우먼”, 33) print(c.dict)
c2 = C(“수퍼맨”) print(c2.dict)
6.5 Mixin 패턴 이해하기
6.5.1 메서드만 처리하는 Mixin 클래스 정의
- Mixin 클래스 하나를 상속처리
import operator as op
class OpMixin :
def aroper(self,op_code) :
return {'+':op.add,
'*':op.mul}[op_code] \
(self.x, self.y if type(self.y) not in [str,list, tuple] \
else self.y if op_code != "*"
else len(self.y))
class Num(OpMixin) : def init(self, x,y) : self.x = x self.y = y
class STR(OpMixin) : def init(self, x,y) : self.x = x self.y = y
class LIST(OpMixin) : def init(self, x,y) : self.x = x self.y = y
n = Num(5,6)
print(n.aroper(“+”)) print(n.aroper(“*”))
s = STR(“Hello”,”World”)
print(s.aroper(“+”)) print(s.aroper(“*”))
l = LIST([1,2,3,4],[6,7])
print(l.aroper(“+”)) print(l.aroper(“*”))
6.5.2 Mixin 다중 상속 시 주의할 사항
- 여러 Mixin 클래스에 동일한 메소드
class AMixin : def method(self) : return “A Mixin”
class BMixin : def method(self) : return “B Mixin”
class A(AMixin, BMixin) : pass
a = A() print(a.method())
class AB(AMixin, BMixin) : def init(self,code) : self.code = code
def method(self) :
if self.code == "B" :
return BMixin.method(self)
else :
return AMixin.method(self)
ab = AB(“B”) print(ab.method())
- Mixin 클래스 다중상속 처리: 다른 메소드 이름
class AMixin : def getname(self) : return self.name
class BMixin : def getage(self) : return self.age
class AB(AMixin, BMixin) : def init(self,name,age) : self.name = name self.age = age
ab = AB(“다중상속”,33) print(ab.getname()) print(ab.getage())
7. 다형성(Polymorphism)
7.1 다형성이란
- 다형성
- 프로그래밍 언어의 자료형 내 요소들이 다양한 곳에 내포되어 처리하는 것
- 특히 객체지향 프로그래밍에서는 상속을 받을 경우 부모와 자식 클래스 내에 메서드들이 동일하게 구현되어 처리하는 것을 말함
- 프로그래밍에서의 다형성은 그 프로그래밍 언어의 자료형 체계의 성질을 나타냄
- 프로그래밍 언어의 각 요소들(상수, 변수, 식, 오브젝트, 함수, 메서드 등)이 다양한 자료형에 속하는 것이 허가되는 성질
- 다형성의 반대 속성: 단형성. 프로그래밍 언어의 각 요소가 한 가지 형태만 가지는 성질
- 다형성의 실질적인 재정의
- 오버라이딩: 부모의 기능을 사용하지 않고 자식의 기능으로 특화하는 방법
- 오버로딩: 동일한 기능을 여러 개로 분리해서 사용하는 방법
- 파이썬은 이름으로만 관리하므로 동일한 기능을 여러 개로 분리할 수 없지만 특정 모듈을 사용해서 오버로딩이 가능함
7.2 매서드 오버라이딩(Overriding)
- 부모 클래스의 메소드를 오버라이딩
class Parent1 : def init(self,name) : print(“ Parent1 “) self.name = name def getname(self) : return self.name
class Parent2 : def init(self,age) : print(“ Parent2 “) self.age = age def getage(self) : return self.age
class Child2(Parent1, Parent2) :
def __init__(self,name, age=None) :
super().__init__(name)
if age is not None :
Parent2.__init__(self,age)
def getname(self) :
return "child " + self.name
def getage(self) :
return "child " + str(self.age)
c = Child2(“오버라이딩”, 33)
print(c.getname()) print(c.getage())
print(Parent1.getname(c)) print(Parent2.getage(c))
7.3 메서드 오버로딩(Overloading)
- overload 모듈을 이용
!pip install –upgrade overload
from overload import overload
class A : @overload def method(self) : print(“ no args method “)
@method.add
def method(self, x) :
print(" one args method "+ x)
@method.add
def method(self, x,y) :
print(" two args method "+ x,y)
a = A()
a.method() a.method(“hello”) a.method(“hello”,”world”)
import pprint
pprint.pprint(A.dict)
print(type(A.method)) pprint.pprint(A.method.dict)
7.4 연산자 오버로딩(Operator Overloading)
- 연산자 오버로딩 이해하기
class Person : def init(self,name,age) : self.name = name self.age = age
class Parent(Person) : def init(self,name,age) : print(“ Parent class “) self.name = name self.age = age
class Child(Person) : def init(self,name,age) : print(“ Child class “) self.name = name self.age = age
p = Parent(“서희”,55) c = Child(“서준”,17)
class Person : def init(self,name,age) : print(“ Person class “) self.name = name self.age = age
class Parent(Person) : def init(self,name,age,pa_code) : super().init(name,age) self.pa_code = pa_code
def ischild(self,child) :
return True if self is child.pa_id else False
class Child(Person) : def init(self,name,age,pa_code,pa_id) : super().init(name,age) self.pa_code = pa_code self.pa_id = pa_id
def isparent(self, parent) :
return True if parent is self.pa_id else False
p = Parent(“서아빠”,56,”p”) c = Child(‘서준’,19,”c”,p)
print(p.ischild(c)) print(c.isparent(p))
7.5 덕 타이핑(Duck typing) 패턴 이해하기
- 함수 내에서 인터페이스 처리
class Duck : def say(self) : return “quack quack”
class Person : def say(self) : return “Hello !”
def say(obj) : return obj.say()
d = Duck() p = Person()
print(say(d)) print(say(p))
- class내에서 인터페이스 제공
class Duck : def say(self) : return “quack quack”
class Person : def say(self) : return “Hello !”
class Say : @staticmethod def say(obj) : return obj.say()
d = Duck() p = Person()
print(Say.say(d)) print(Say.say(p))
8. 메타 클래스(Meta Class)
8.1 메타 클래스와 클래스 정의로 클래스 만들고 비교하기
8.1.1 파이썬에서 메타 클래스로 클래스가 만들어지는 순서
- 적절한 클래스 결정
- 클래스 네임스페이스 준비
- 클래스의 본체 실행
- 클래스 객체를 생성하여 반환값으로 제공
- 메타클래스로 클래스 생성하기
import pprint
namespace = { ‘name’ : “메타클래스로 클래스 생성”} bases = (object,) classname = “Klass”
Klass = type(classname, bases, namespace)
print(type(Klass)) print(Klass) pprint.pprint(Klass.dict)
class Klass : name = “ 클래스 정의문으로 클래스 생성”
print(type(Klass)) print(Klass) pprint.pprint(Klass.dict)
8.1.2 클래스 상속과 메타 클래스의 관계
- 사용자 메타클래스로 변경하기
class MyMeta(type) : pass
class Klass(metaclass=MyMeta) : pass
print(Klass) print(Klass.class)
class A : def init(self) : self.b = b()
9. 연관관계(Association)
9.1 연관관계
- 구성관계 (composition)
class Salary: def init(self,pay): self.pay=pay
def get_total(self):
return (self.pay*12)
class Employee: def init(self,pay,bonus): self.pay=pay self.bonus=bonus self.obj_salary=Salary(self.pay)
def annual_salary(self):
return "Total: " + str(self.obj_salary.get_total()+self.bonus)
obj_emp=Employee(100,10) print (obj_emp.annual_salary())
- 집합 관계(Aggregation)
class Salary: def init(self,pay): self.pay=pay
def get_total(self):
return (self.pay*12)
class Employee: def init(self,pay,bonus): self.pay=pay self.bonus=bonus
def annual_salary(self):
return "Total: " + str(self.pay.get_total()+self.bonus)
obj_sal=Salary(100) obj_emp=Employee(obj_sal,10) print (obj_emp.annual_salary())
del obj_emp print(obj_sal)
9.2 위임 패턴 처리
- 위임 메소드를 사용하기
class Person : def init(self,name,age) : self.name = name self.age = age
class Student : def init(self, name,age,college) : self.person = Person(name,age) self.college = college
s = Student(“연관”,22,”숭실대”) print(s.dict)
class Person : def init(self,name,age) : self.name = name self.age = age
def getname(self) :
return self.name
def getage(self) :
return self.age
class Student : def init(self, name,age,college) : self.person = Person(name,age) self.college = college
def getname(self) :
return self.person.getname()
def getage(self) :
return self.person.getage()
s = Student(“위임”,22,”숭실대”) print(s.getname()) print(s.getage())