반응형
학습목표
- 클래스와 오브젝트에 대해 이해한다.
- 클래스를 정의하고 활용 할 수 있다.
class란?
- 실세계의 것을 모델링하여 속성(attribute)와 행위(method)를 갖는 데이터 타입이다.
- python에서의 string, int, list, dict.. 모두가 다 클래스로 존재한다.
- 예를들어 학생이라는 클래스를 만든다면, 학생을 나타내는 속성과 학생이 행하는 행동을 함께 정의 할 수 있음
- 사용하고자하는 데이터(변수)와 데이터를 다루는 연산(함수)를 하나로 캡슐화(encapsulation)하여 클래스로 표현한다.
object 란?
- 클래스로 생성되어 구체화된 객체(인스턴스)이다.
- 파이썬의 모든 것(int, str, list..etc)은 객체(인스턴스)이다.
- 실제로 class가 인스턴스화 되어 메모리에 상주하는 상태를 의미한다.
- class가 설계도, object는 실제로 설계도를 기반으로 만든 것을 말한다.
class 선언하기
- 객체를 생성하기 위해선 객체의 설계도가 되는 class를 미리 선언해야 한다.
In [1]:
class Person:
pass
In [2]:
class MyClass:
'이것은 나의 클래스 입니다.'
pass
In [3]:
MyClass.__doc__
Out[3]:
'이것은 나의 클래스 입니다.'
In [4]:
str.__doc__
Out[4]:
"str(object='') -> str\nstr(bytes_or_buffer[, encoding[, errors]]) -> str\n\nCreate a new string object from the given object. If encoding or\nerrors is specified, then the object must expose a data buffer\nthat will be decoded using the given encoding and error handler.\nOtherwise, returns the result of object.__str__() (if defined)\nor repr(object).\nencoding defaults to sys.getdefaultencoding().\nerrors defaults to 'strict'."
In [5]:
list.__doc__
Out[5]:
'Built-in mutable sequence.\n\nIf no argument is given, the constructor creates a new empty list.\nThe argument must be an iterable if specified.'
In [6]:
Person.__doc__
In [9]:
class Person:
'''이것은 사람을 추상화 한
클래스 입니다.'''
name = 'kang'
def greet(self):
print('hello~~')
kang = Person()
kang.greet()
kim = Person()
kim.name = 'kim'
print(kim.name)
hello~~
kim
In [10]:
Person.__doc__
Out[10]:
'이것은 사람을 추상화 한 \n 클래스 입니다.'
In [11]:
Person.__dict__
Out[11]:
mappingproxy({'__module__': '__main__',
'__doc__': '이것은 사람을 추상화 한 \n 클래스 입니다.',
'name': 'kang',
'greet': <function __main__.Person.greet(self)>,
'__dict__': <attribute '__dict__' of 'Person' objects>,
'__weakref__': <attribute '__weakref__' of 'Person' objects>})
In [12]:
kang.__dict__
Out[12]:
{}
In [13]:
kim.__dict__
Out[13]:
{'name': 'kim'}
__init__(self)
- 생성자, 클래스 인스턴스가 생성될 때 호출된다.
- self인자는 항상 첫번째에 오며 자기 자신을 가리키다.
- 이름이 꼭 self일 필요는 없지만, 관례적으로 self로 사용한다.
- 생성자에서는 해당 클래스가 다루는 데이터를 정의한다.
- 이 데이터를 멤버 변수(member variable) 또는 속성(attribute)라고 함
In [18]:
class Pen:
def __init__(self):
self.color = 'black'
def draw(self):
print(self.color,'색으로 그려요!! ' )
p1 = Pen()
print(p1.color)
black
In [21]:
class Pen:
def __init__(self,color):
self.color = color #color 초기화
def draw(self):
print(self.color,'색으로 그려요!! ' )
p2 = Pen('red')
p3 = Pen('blue')
name = 'kang' #name 변수 초기화
a = 0 # a 변수 초기화
#Pen... 속성 color
In [22]:
p2.color
p2.draw()
p3.draw()
red 색으로 그려요!!
blue 색으로 그려요!!
In [1]:
class Person:
def __init__(self,name):
print('person의 생성자 실행!@!!')
self.name = name
self.age = 1
knag = Person('kang')
kim = Person('kim')
print('이름',knag.name)
print('나이',knag.age)
print('이름',kim.name)
print('나이',kim.age)
person의 생성자 실행!@!!
person의 생성자 실행!@!!
이름 kang
나이 1
이름 kim
나이 1
In [37]:
class Person:
def __init__(self,name,age=1):
print('person의 생성자 실행!@!!')
self.name = name
self.age = age
kk = Person('carami',20)
print('이름',kk.name)
print('나이',kk.age)
mm = Person('mmas')
print('이름',mm.name)
print('나이',mm.age)
person의 생성자 실행!@!!
나이 carami
self
- 파이썬의 method는 항상 첫번째 인자로 self를 전달한다.
- self는 현재 해당 메쏘드가 호출되는 객체 자신을 가리킨다.
- 반드시 이름이 self일 필요는 없으나 관례적으로 self를 사용한다.
- 위치는 항상 맨 첫번째 parameter이다.
In [38]:
#속성으로 name과 speed를 갖는 Car 클래스를 정의하세요.
class Car:
def __init__(self):
self.name = 'None'
self.speed = 0
#본인이 갖고 싶은 차를 생성해 보세요.
sonata = Car()
sonata.name = 'sonota'
sonata.speed = 100
print(sonata.name, sonata.speed)
sonota 100
In [41]:
# 위의 Car 클래스에 차의 이름과 속도를 알려주는 info 라는 이름의 메소드를 정의하세요.
class Car:
def __init__(self):
self.name = 'None'
self.speed = 0
def info(self):
print(f'내 차의 이름은 {self.name} 이고, 현재 속도는 {self.speed} 입니다. ')
sonata = Car()
sonata.name = 'sonota'
sonata.speed = 100
sonata.info()
내 차의 이름은 sonota 이고, 현재 속도는 100 입니다.
In [43]:
dir()
Out[43]:
['Car',
'In',
'MyClass',
'Out',
'Pen',
'Person',
'_',
'_10',
'_11',
'_12',
'_13',
'_17',
'_3',
'_39',
'_4',
'_40',
'_42',
'_5',
'__',
'___',
'__builtin__',
'__builtins__',
'__doc__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'_dh',
'_i',
'_i1',
'_i10',
'_i11',
'_i12',
'_i13',
'_i14',
'_i15',
'_i16',
'_i17',
'_i18',
'_i19',
'_i2',
'_i20',
'_i21',
'_i22',
'_i23',
'_i24',
'_i25',
'_i26',
'_i27',
'_i28',
'_i29',
'_i3',
'_i30',
'_i31',
'_i32',
'_i33',
'_i34',
'_i35',
'_i36',
'_i37',
'_i38',
'_i39',
'_i4',
'_i40',
'_i41',
'_i42',
'_i43',
'_i5',
'_i6',
'_i7',
'_i8',
'_i9',
'_ih',
'_ii',
'_iii',
'_oh',
'exit',
'get_ipython',
'kang',
'kim',
'kk',
'knag',
'mm',
'p1',
'p2',
'p3',
'quit',
'sonata']
In [39]:
dir(sonata)
Out[39]:
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'name',
'speed']
mehtod 정의
- 파이썬에서는 메서드의 첫번째 매개변수 이름은 관례적으로 self를 사용한다.
- obj.method() 형태로 호출된다.
In [45]:
#Counter 클래스를 정의 하세요. 멤버변수는 num 을 갖고 있고,
#메소드는 num을 1씩 증가시키는 메소드, num을 0으로 초기화 하는 메소드,
#현재 num 의 값을 알려주는 메서드 를 정의 하세요.
class Counter:
def __init__(self):
self.num = 0
def increment(self):
self.num += 1
def reset(self):
self.num = 0
def currentValue(self):
print('현재값은:', self.num)
c = Counter()
c.currentValue()
c.increment()
c.increment()
c.currentValue()
c.reset()
c.currentValue()
현재값은: 0
현재값은: 2
현재값은: 0
In [ ]:
In [ ]:
비공개속성
In [11]:
class Person:
def __init__(self):
self.__name = 'kang' #비공개 속성
self.age = 20
def getName(self):
return self.__name
def __setName(self,name): #비공개메서드
self.__name = name
def sName(self,name):
#다른구현이 필요하다면 구현..
self.__setName(name)
k = Person()
# print(k.__name)
print(k.age)
print(k.getName())
k.sName('carami')
print(k.getName())
20
kang
carami
In [ ]:
클래스 속성 VS 인스턴스 속성
In [13]:
class Bag:
def __init__(self):
self.items = []
def putItem(self,item):
self.items.append(item)
cbag = Bag()
cbag.putItem('candy')
cbag.putItem('book')
cbag.putItem('pen')
kbag = Bag()
kbag.putItem('phone')
print('kbag',kbag.items)
print('cbag', cbag.items)
kbag ['phone']
cbag ['candy', 'book', 'pen']
In [14]:
class Bag:
items = []
name = ''
def putItem(self,item):
self.items.append(item)
name = "dfjdk"
cbag = Bag()
cbag.putItem('candy')
cbag.putItem('book')
cbag.putItem('pen')
kbag = Bag()
kbag.putItem('phone')
print('kbag',kbag.items)
print('cbag', cbag.items)
kbag ['candy', 'book', 'pen', 'phone']
cbag ['candy', 'book', 'pen', 'phone']
method type
- instance method - 객체로 호출된다.
- 메서드는 객체가 생성될때 만들어진다.
- class method(static method) - class로 호출
- 클래스 메서드의 경우 객체가 생성되기 전에 미리 생성됨으로 객체를 통해 호출하지 않는다.
In [15]:
class Cal:
def add(self,a,b):
print(a+b)
cal = Cal()
cal.add(1,2)
3
In [17]:
class Cal:
@staticmethod
def add(a,b):
print(a+b)
Cal.add(1,2)
3
In [24]:
class Cal:
result = 0
def __init__(self):
self.name = 'test'
@classmethod
def cls_add(cls,a,b):
cls.result= a + b
print(cls.name)
return cls.result
@staticmethod
def add(a,b):
return a+b
Cal.add(2,3)
Cal.cls_add(2,3)
c = Cal() # 객체 생성... c는 인스턴스
c.name
------------------------------------------
AttributeErrorTraceback (most recent call last)
Input In [24], in <cell line: 15>()
12 return a+b
14 Cal.add(2,3)
---> 15 Cal.cls_add(2,3)
Input In [24], in Cal.cls_add(cls, a, b)
5 @classmethod
6 def cls_add(cls,a,b):
7 cls.result= a + b
----> 8 print(cls.name)
9 return cls.result
AttributeError: type object 'Cal' has no attribute 'name'
In [ ]:
In [ ]:
Class Inheritance (상속)
- 다른 클래스의 기능을 그대로 물려받을 수 있다.
- 기존 클래스에 기능 일부를 추가하거나, 변경하여 새로운 클래스를 정의한다.
- 코드를 재사용할 수 있게된다.
- 상속 받고자 하는 대상인 기존 클래스는 (Parent, Super, Base class 라고 부른다.)
- 상속 받는 새로운 클래스는(Child, Sub, Derived class 라고 부른다.)
- 의미적으로 is-a관계를 갖는다
In [25]:
class Parent:
def __init__(self):
self.i = 10
class Child(Parent): #상속!!
pass
c = Child()
print(c.i)
10
In [34]:
class Parent:
def __init__(self):
print('Parent생성자 실행')
self.i = 10
class Child(Parent): #상속!!
def __init__(self):
self.i = 20
print('Child 생성자 실행')
def test(self):
pass
k = Child()
print(k.i)
p = Parent()
Child 생성자 실행
20
Parent생성자 실행
In [ ]:
In [ ]:
In [53]:
class Person:
def __init__(self,name):
self.name = name
def eat(self, food):
print('{}은 {}를 먹습니다.'.format(self.name,food))
In [51]:
class Student(Person):
# def __init__(self):
# self.name = 'student'
pass
#Student클래스에 __init__ 메서드가 없다면, 부모 클래스의 __init__메서드를 실행한다.
s = Student('carami') #부모클래스의 __init__메서드는 name 을 원하므로, Student객체를 생성할때... name을 알려줘야한다.
s.eat('밥')
carami은 밥를 먹습니다.
In [52]:
class Student(Person):
def __init__(self): #Student클래스가 __init__ 메서드를 가진경우는 Person의 __init__ 메소드는 실행되지 않는다.
self.name = 'student'
kang = Student()
s.eat('빵')
carami은 빵를 먹습니다.
method override
- 부모 클래스의 method를 재정의(override)한다.
- 하위 클래스(자식 클래스) 의 인스턴스로 호출시, 재정의된 메소드가 호출된다.
In [55]:
class Person:
def __init__(self,name):
self.name = name
def eat(self, food):
print('{}은 {}를 먹습니다.'.format(self.name,food))
class Student(Person):
def __init__(self,name):
self.name = name
def eat(self, food):
print('{}은 {}를 맛있게 먹습니다.'.format(self.name,food))
carami = Student('carami')
carami.eat('밥')
carami은 밥를 맛있게 먹습니다.
super
- 하위클래스(자식 클래스)에서 부모클래스의 method를 호출할 때 사용한다.
In [58]:
class Parent:
def hello(self):
print('안녕')
print('나는 여기에 복잡하고')
print('어려운 것들을 많이 구현하고 있어요~~ ')
class Child(Parent):
def hello(self):
super().hello()
print('오늘은 날씨가 좋네요~~^^')
def study(self):
print('공부를 재밌게 해요~~')
kim = Child()
kim.hello()
안녕
나는 여기에 복잡하고
어려운 것들을 많이 구현하고 있어요~~
오늘은 날씨가 좋네요~~^^
In [65]:
class Person:
def __init__(self,name):
print('Person의 __init__실행')
self.name = name
self.age = 20
def eat(self, food):
print('{}은 {}를 먹습니다.'.format(self.name,food))
class Student(Person):
def __init__(self, name,schoolName):
print('Student 의 __init__ 실행')
# self.name = name
super().__init__(name)
self.schoolName = schoolName
def sayHello(self):
print('안녕~~~!!')
kim = Student('kim','kkk')
kim.eat('candy')
kim.sayHello()
Student 의 __init__ 실행
Person의 __init__실행
kim은 candy를 먹습니다.
안녕~~~!!
다중상속
In [72]:
class P1:
def hello(self):
print('hello p111111111111111111')
class P2:
# def hello(self):
# print('hello p222222222222222222')
pass
class C(P1):
def hello2(self):
print('hello cccccccccccccccccccc')
class D(C,P2):
pass
test = D()
test.hello()
hello p111111111111111111
In [73]:
print(D.mro())
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.P1'>, <class '__main__.P2'>, <class 'object'>]
추상클래스
In [80]:
from abc import *
class 새(metaclass = ABCMeta):
def 먹다(self):
print('맛있게 먹어요.')
def 날다(self):
print('하늘을 날아요')
@abstractmethod
def 노래하다(self):
pass
#추상클래스는 미완성 클래스다. 때문에 객체를 생성 할 수없다.
# a = 새()
class 앵무새(새):
def 노래하다(self):
print('앵무새가 노래해요~')
봄봄 = 앵무새()
연습문제
- 멤버변수 w,h 를 갖는 Shape 클래스를 정의 하시오.
- Sahpe 클래스는 도형을 그리는 draw()라는 추상 메소드를 포함하게 하세요.
- Shape을 상속받은 Rect, Circle 클래스를 정의하고, draw()메소드를 적절하게 구현하세요.
- 이때 Circle는 반지름을 나타내는 멤버변수 r 을 추가해주세요.
- 도형은 면적을 구하는 메서드도 추가해 보세요.
In [5]:
class Shape(metaclass = ABCMeta):
def __init__(self,w,h):
self.w = w
self.h = h
@abstractmethod
def draw(self):
pass
class Circle(Shape):
def __init__(self,r):
# super().__init__(w,h)
self.r = r
def draw(self):
print('원을 그려요!! ')
def calculate(self):
return (self.r**2) *3.14
class Rect(Shape):
def draw(self):
print('사각형을 그려요!!')
def calculate(self):
return self.w*self.h
c = Circle(3)
c.draw()
print(c.calculate())
r = Rect(3,4)
r.draw()
print(r.calculate())
원을 그려요!!
28.26
사각형을 그려요!!
12
In [2]:
from abc import *
class Shape:
def __init__(self,w,h):
self.w = w
self.h = h
@abstractmethod
def draw(self):
pass
class Rect(Shape):
def __init__(self,w,h):
self.w = w
self.h = h
def draw(self):
print("해당사각형의 면적은 {}".format(self.w*self.h))
class Circle(Shape):
def __init__(self,r):
self.r = r
def draw(self):
print("해당원의 면적은 {}".format((self.r**2)*3.14))
rect = Rect(3,4)
rect.draw()
circle = Circle(4)
circle.draw()
해당사각형의 면적은 12
해당원의 면적은 50.24
In [4]:
print(type(Shape))
<class 'type'>
In [103]:
dir(Shape)
Out[103]:
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'draw']
special method
- 로 시작 로 끝나는 특수 함수다.
- 해당 메쏘드들을 구현하면, 커스텀 객체에 여러가지 파이썬 내장 함수나 연산자를 적용 가능하다.
- 오버라이딩 가능한 함수 목록은 아래 링크에서 참조
In [127]:
class Shape(metaclass = ABCMeta):
def __init__(self,w,h):
self.w = w
self.h = h
@abstractmethod
def draw(self):
pass
class Circle(Shape):
def __init__(self,r):
# super().__init__(w,h)
self.r = r
def draw(self):
print('원을 그려요!! ')
def calculate(self):
return (self.r**2) *3.14
class Rect(Shape):
def draw(self):
print('사각형을 그려요!!')
def calculate(self):
return self.w*self.h
def __add__(self,rect):
new_w = rect.w + self.w
new_h = rect.h + self.h
return Rect(new_w,new_h)
def __eq__(self, rect):
print(self.calculate())
print(rect.calculate())
return self.calculate() == rect.calculate()
In [128]:
r1 = Rect(2,3)
print(r1.calculate())
6
In [129]:
r2 = Rect(3,2)
print(r2.calculate())
6
In [130]:
r1 == r2
6
6
Out[130]:
True
__add__() # + 연산자로 호출
__sub__() # - 연산자로 호출
__mul__() # * 연산자로 호출
__truediv__() # / 연산자로 호출
In [120]:
new_r = r1 + r2
r3 = r1.__add__(r2)
print(r3.w,r3.h)
print(r3.calculate())
5 5
25
In [119]:
new_r.calculate()
print(new_r.w, new_r.h)
5 5
In [ ]:
dir()
In [11]:
class AbcTest(metaclass=ABCMeta):
# @abstractmethod
def test(self):
pass
def p(self):
print('hi')
In [12]:
c = AbcTest()
c.p()
hi
In [99]:
dir(AbcTest)
Out[99]:
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'test']
In [101]:
class aaTest(metaclass = ABCMeta):
pass
class bbTest(aaTest):
pass
a = bbTest()
'경기도 인공지능 개발 과정 > Python' 카테고리의 다른 글
Python pymysql 사용하기 (0) | 2022.05.28 |
---|---|
Python 예외처리 (0) | 2022.05.28 |
Python 파일 입출력 (0) | 2022.05.28 |
Python 함수, lambda 함수 (0) | 2022.05.28 |
Python 조건문과 반복문(While, For) (0) | 2022.05.28 |