python/파이썬 기본

10. 클래스와 인스턴스

Abokadoh 2023. 2. 13. 15:06

1. class

  • 실세계의 것을 모델링하여 속성(attribute)와 동작(method)를 갖는 데이터 타입
  • python에서의 string, int, list, dict.. 모두가 다 클래스로 존재한다.
  • 예를들어 학생이라는 클래스를 만든다면, 학생을 나타내는 속성과 학생이 행하는 행동을 함께 정의할 수 있다.
  • 따라서, 다루고자 하는 데이터(변수)와 데이터를 다루는 연산(함수)를 하나로 캡슐화(encapsulation)하여 클래스로 표현
  • 모델링에서 중요시 하는 속성에 따라 클래스의 속성과 행동이 각각 달라진다.

2. class 선언하기

객체를 생성하기 위해선 객체의 모체가 되는 class를 미리 선언해야 한다.

class person: #person이라는 클래스를 만들었다.
    pass
bob = person()
cathy = person()

a = list()
b = list()

3. __init__(self)

  • 생성자, 클래스 인스턴스가 생성될 때 호출됨
  • self인자는 항상 첫번째에 오며 자기 자신을 가르킨다.
  • 이름이 꼭 self일 필요는 없지만, 관례적으로 self로 사용한다.
  • 생성자에서는 해당 클래스가 다루는 데이터를 정의한다.
    • 이 데이터를 멤버 변수(member variable) 또는 속성(attribute)라고 한다.
# <in>
class Person:
    def __init__(self):
        print(self, 'is generated')
        self.name = 'Kate'
        self.age = 10
p1 = Person()
p2 = Person()

p1.name = 'aaron' # 변경 가능
p1.age = 20 #변경 가능

print(p1.name, p1.age)


# <out>
<__main__.Person object at 0x7f88619d3100> is generated
<__main__.Person object at 0x7f88619d3610> is generated
aaron 20
# <in>
class Person:
    def __init__(self, name, age = 10):
        print(self, 'is generated')
        self.name = name
        self.age = age

p1 = Person('Bob', 30)
p2 = Person('Kate', 20)
p3 = Person('Aaron')

print(p1.name, p1.age)
print(p2.name, p2.age)
print(p3.name, p3.age)


# <out> 
<__main__.Person object at 0x7f88619d32e0> is generated
<__main__.Person object at 0x7f88708553a0> is generated
<__main__.Person object at 0x7f88619d3100> is generated
Bob 30
Kate 20
Aaron 10

4. self

  • python의 method는 항상 첫번째 인자로 self를 전달한다.
  • self는 현재 해당 method가 호출되는 객체 자신을 가르킨다.
  • C++/C#, Javathis에 해당한다.
  • 역시, 이름이 self일 필요는없으나, 위치는 항상 맨 처음의 parameter이며 관례적으로 self를 사용한다.
class Person:
    def __init__(self, name, age):
        print('self: ', self)
        self.name = name
        self.age = age

    def sleep(self):
        print('self:', self)
        print(self.name, '은 잠을 잡니다.')

a = Person('Aaron', 20)
b = Person('Bob', 30)

print(a)
print(b)

a.sleep()
b.sleep()


# <out>
self:  <__main__.Person object at 0x7f8861a71970>
self:  <__main__.Person object at 0x7f8861a12430>
<__main__.Person object at 0x7f8861a71970>
<__main__.Person object at 0x7f8861a12430>
self: <__main__.Person object at 0x7f8861a71970>
Aaron 은 잠을 잡니다.
self: <__main__.Person object at 0x7f8861a12430>
Bob 은 잠을 잡니다.

5. method 정의

  • 멤버함수라고도 하며, 해당 클래스의 object에서만 호출가능
  • method는 객체 레벨에서 호출되며, 해당 객체의 속성에 대한 연산을 행한다.
  • {obj}.{method}() 형태로 호출됨
# 1. 숫자를 하나 증가
# 2. 숫자를 0으로 초기화

class Counter:
    def __init__(self):
        self.num = 0
    def increment(self):
        self.num += 1
    def reset(self):
        self.num = 0
    def print_current_value(self):
        print('현재값은:', self.num)

c1 = Counter()
c1.print_current_value()
c1.increment()
c1.increment()
c1.increment()
c1.print_current_value()

c1.reset()

c1.print_current_value()

c1.reset()

c1.print_current_value()

c2 = Counter()
c2.increment()
c2.print_current_value()


# <out>
현재값은: 0
현재값은: 3
현재값은: 0
현재값은: 0
현재값은: 1

6. method type

  • instance method - 객체로 호출
    • method는 객체 레벨로 호출되기 때문에, 해당 method를 호출한 객체에만 영향을 미친다.
  • class method(static method) - class로 호출
    • class method의 경우, 클래스 레벨로 호출되기 때문에, 클래스 멤버 변수만 변경 가능
# <in>
class Math:
    def add(a, b):
        return a + b
    def multiply(a, b):
        return a * b

Math.add(10, 20)
Math.multiply(10, 20)


# <out>
200

7. Class Inheritance (상속)

  • 기존에 정의해둔 클래스의 기능을 그대로 물려받을 수 있다.
  • 기존 클래스에 기능 일부를 추가하거나, 변경하여 새로운 클래스를 정의한다.
  • 코드를 재사용할 수 있게 된다.
  • 상속 받고자 하는 대상인 기존 클래스는 Parent, Super, Base class라고 부른다.
  • 의미적으로 is-a관게를 갖는다.
# <in>
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def eat(self, food):
        print('{}은 {}를 먹습니다.'.format(self.name, food))
    def sleep(self, minute):
        print('{}은 {}분동안 잡는다.'.format(self.name, minute))
    def work(self, minute):
        print('{}은 {}분동안 일합니다.'.format(self.name, minute))

class Student(Person):
    def __init__(self, name, age):
        self.name = name
        self.age = age
class Employee(Person):
    def __init__(self, name, age):
        self.name = name
        self.age = age

bob = Employee('Bob', 25)
bob.eat('BBQ')
bob.sleep(30)
bob.work(60)


# <out>
Bob은 BBQ를 먹습니다.
Bob은 30분동안 잡는다.
Bob은 60분동안 일합니다.

8. mothod override

  • 부모 클래스의 method를 재정의(override)
  • 하위 클래스(자식 클래스)의 인스턴스로 호출시, 재정의된 method가 호출됨
# <in>
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def eat(self, food):
        print('{}은 {}를 먹습니다.'.format(self.name, food))
    def sleep(self, minute):
        print('{}은 {}분동안 잡는다.'.format(self.name, minute))
    def work(self, minute):
        print('{}은 {}분동안 일합니다.'.format(self.name, minute))

class Student(Person):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def work(self, minute):
        print('{}은 {}분동안 공부합니다.'.format(self.name, minute))

class Employee(Person):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def work(self, minute):
        print('{}은 {}분동안 업무를 합니다.'.format(self.name, minute))

bob = Employee('Bob', 25)
bob.eat('BBQ')
bob.sleep(30)
bob.work(60)


# <out>
Bob은 BBQ를 먹습니다.
Bob은 30분동안 잡니다.
Bob은 60분동안 업무를 합니다.

9. super

하위클래스(자식 클래스)에서 부모클래스의 method를 호출할 때 사용

# <in>
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self, food):
        print('{}은 {}를 먹습니다.'.format(self.name, food))

    def sleep(self, minute):
        print('{}은 {}분동안 잡니다.'.format(self.name, minute))

    def work(self, minute):
        print('{}은 {}분동안 준비를 합니다.'.format(self.name, minute))

class Student(Person):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def work(self, minute):
        super().work(minute)
        print('{}은 {}분동안 공부합니다.'.format(self.name, minute))

class Employee(Person):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def work(self, minute):
        super().work(minute)
        print('{}은 {}분동안 업무를 합니다.'.format(self.name, minute))

bob = Employee('Bob', 25)
bob.eat('BBQ')
bob.sleep(30)
bob.work(60)


# <out>
Bob은 BBQ를 먹습니다.
Bob은 30분동안 잡니다.
Bob은 60분동안 준비를 합니다.
Bob은 60분동안 업무를 합니다.

10. special method

# <in>
# Point 
# 2차원 좌표평면 각 점(x, y) 
# 연산
# 두점 의 덧셈, 뺄셈 (1, 2) + (3, 4) = (4, 6)
# 한점과 숫자의 곱셈 (1,  2) * 3 = (3, 6)
# 그 점의 길이 (0,0) 부터의 거리
# x, y 값 가져오기
# 출력하기

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y 

    def __add__(self, pt):
        new_x = self.x + pt.x
        new_y = self.y + pt.y
        return Point(new_x, new_y)

    def __sub__(self, pt):
        new_x = self.x - pt.x
        new_y = self.y - pt.y
        return Point(new_x, new_y)

    def __mul__(self, factor):
        return Point(self.x * factor, self.y * factor)

    def __getitem__(self, index):
        if index == 0:
            return self.x
        elif index == 1:
            return self.y
        else:
            return -1

    def __len__(self):
        return self.x ** 2 + self.y ** 2

    def __str__(self):
        return '({}, {})'.format(self.x, self.y)

p1 = Point(3, 4)
p2 = Point(2, 7)

a = 1 + 2
p3 = p1 + p2
p4 = p1 - p2

# p5 = p1.multiply(3)
p5 = p1 * 3

print(len(p1))

# p1[0] -> x
# p1[1] -> y
print(p1[0])
print(p1[1])
print(p1)
print(p2)
print(p3)
print(p4)
print(p5)


# <out>
25
3
4
(3, 4)
(2, 7)
(5, 11)
(1, -3)
(9, 12)

- object란?

  • 클래스로 생성되어 구체화된 객체(인스턴스)
  • 파이썬의 모든 것(int, str, list, …)은 객체(인스턴스)이다.
  • 실제로 class가 인스턴스화 되어 메모리에 상주하는 상태를 의미
  • class가 빵틀이라면, object는 실제로 빵틀로 찍어낸 빵이라고 비유가 가능하다.