Python | 클래스(Class)와 객체(Object)

Stellar·2021년 5월 24일
0

Python

목록 보기
11/36
post-thumbnail
post-custom-banner

클래스와 객체

Q. 클래스는 함수와 다른 것인가?

A. 클래스는 함수의 상위 개념이다. 클래스 안에 함수를 작성한다.
메소드는 함수이다. 클래스에 정의된 함수를 사용할 땐 메소드라한다.
함수 = 동작한다 = 메소드

  • 클래스는 대분류, 함수는 중분류라고 보자.

✔️ 절차 지향형과 객체 지향형

절차 지향형

흐름에 따라 절차를 따르는 것.

객체(Object) 지향형

현실 세계의 모든 것을 객체로 만든다. 객체의 상태(state)는 객체의 속성이다.
객체의 동작(behavior)은 객체가 취할 수 있는 기능.
객체 지향형의 경우 프라이빗 함수, 변수 사용이 가능해 보안을 할 수 있다.

✔️ 클래스 속성이란

속성(== 객체의 상태, state)은 인수이다.

#class 클래스이름:
class Intro:
    def __init__(self, age, name):
        #self.속성 = 값
        self.age = age
        self.name = name

속성 예시

class Person:
    def __init__(self):
        self.hello = '안녕하세요.'
 
    def greeting(self):
        print(self.hello)
 
james = Person()
james.greeting()

========================= RESTART: /Users/boksilhwang/Documents/test.py =========================
안녕하세요.

TV(객체) 예시

상태 - 빨간색이다, 채널번호, 볼륨, 전원 상태 등
동작 - 켜다, 끄다, 채널 변경, 볼륨을 높이다. 등

  • 객체 = 필드(상태) + 메소드(동작)
  • 필드 : 채널, 볼륨
  • 메소드 : 채널 올리기, 볼륨 줄이기, 전원 켜기.

✔️ 객체에 대한 설계도를 클래스라 함.

클래스 = 와플 틀, 따라서 클래스는 객체를 찍어내는 틀과 같다.
객체(인스턴스) = 와플 1, 2, 3 ...
객체의 동작 담당 = 메소드 == 함수

✔️ 캡슐화

캡슐화란 알고리즘과 데이터를 하나로 묶고 내부 코드를 외부로부터 감춘다.
객체 지향은 보안이 된다고 위에서 말했듯 클래스 내부의 코드를 직접적으로 관여할 수 없다.

  • '클래스를 만들다' 가 캡슐화 시키다'로 인식해도 되는가?

1. 클래스 문법

class 클래스이름:
    def 메서드(self):
        코드

✔️ 클래스 사용법

class Counter :
    def reset(self) :
        self.count = 0 #정의해줘야 아래에서 + 1을 해줄 수 있음.
        #.count는 어디서 나온거지? 단순 카운팅하는 메소드인가?

    def increment(self) :
        self.count += 1
    def get(self) :
        return self.count

a = Counter() #변수에 클래스를 할당, a는 객체이기도 하다. 따라서 여러 객체를 만들 수 있다. b = Counter() 등등

a.reset() #.메소드는 함수에 해당한다.
a.increment()
print('카운터 a의 값은', a.get())

#클래스 재활용
b = Counter()

b.reset()
b.increment()
b.increment()
print('카운터 b의 값은', b.get())

✔️ 빈 클래스 만들기

class Person:	# 코드 부분에 pass를 사용
    pass

2. 초기화를 시킨다는 의미

클래스에서 초기화를 시킨다는 의미는 클래스 내부에 어떠한 값을 정의한다는 의미다.
reset() 함수를 만들어 시작 시 매번 초기화를 시킬 필요 없이 __init__ 함수를 사용해 별도의 초기화 메소드 사용없이 클래스를 사용할 수 있다.

  • 매번 초기화하려면 클래스에 .reset() 함수를 정의한 후 아래 코드와 같이 .reset() 메소드를 사용 했어야 함.
a = Counter() #클래스를 변수에 정의

a.reset() #클래스 초기화
a.increment()
print('카운터 a의 값은', a.get())

b = Counter()

b.reset() #클래스 초기화
b.increment()
print('카운터 b의 값은', b.get())

✔️ 하지만 __init__ 함수 사용 시

__init__는 생성자(constructor)라고 한다.
따라서 __init__는 객체에 reset() 메소드를 쓰지않아도 초기화 할 수 있도록 만들어진 기능.
reset 함수는 코드 진행 후 중간에 reset을 할 일이 있을 때, 따로 reset을 사용하면 된다.
__명령어__ 언더바가 두 개인 이유는 파이썬 내부에서 사용한다는 의미.

class Counter :
    def __init__(self) :
        self.count = 0

a = Counter() 

#a.reset() # reset() 없이 바로 사용 가능.
a.increment()
print('카운터 a의 값은', a.get())

✔️ 함수 기본 값과 리셋 시 기본 값 설정법

initValur = 0를 인자로 넣어주고, 클래스를 부를 때 클래스에 인수를 넘겨주면 된다. 인수가 없는 경우 기본 값인 0으로 초기화 한다.

class Counter :
    def __init__(self, initValur = 0) :
        self.count = 0

    def increment(self) :
        self.count += 1
    def get(self) :
        return self.count

a = Counter() 
a.increment()
print('카운터 a의 값은', a.get()) #결과 값 1

b = Counter(100)
b.increment()
print('카운터 b의 값은', b.get())  #결과 값 101

✔️ self 인수

self는 클래스 외부에 정의된 변수(==self)의 이름을 인수로 가진다.
self에는 변수가 자동으로 들어오기 때문에 인수를 별도로 줄 필요 없다.

class Counter :
    def __init__(self, initValur = 0) : #self는 a
        self.count = 0

a = Counter()

클래스 예제. TV 클래스 만들기

class Television :
    def __init__(self, channel, volume, on) :
        self.channel = channel
        self.volume = volume
        self.on = on

    def show(self) :
        print(self.channel, self.volume, self.on)

    def setChannel(self, channel) :
        self.channel = channel

    def getChannel(self) :
        return self.channel

t = Television(9, 10, True)
t.show()

t.setChannel(11)
t.show()
print(t.getChannel())

✔️ 프라이빗 변수와 함수

__ 언더바가 두 개 붙을 경우 클래스 외부에서 변수 변경이 불가하다.
변수에 __을 붙이면 obj.name()으로 프린트해서 바로 가져오진 못 하지만 클래스 내부에 정의된 함수인 obj.getName()으로는 불러 올 수 있다.
한마디로 __을 붙이면 인수를 직접 접근 하는 것이 아닌 함수명(메소드)로만 기능을 실행할 수 있다.
클래스 내 함수에서 인수를 활용한 변수가 없으면 그 값에 대한건 아예 접근이 불가능한거지.

프라이빗 변수 에러 예시

class Student :
    def __init__(self, name = None, age = 0) :
        self.__name = name
        self.__age = age

obj = Student('Hong', 21)
print(obj.__age)

========================= RESTART: /Users/boksilhwang/Documents/test.py =========================
Traceback (most recent call last):
  File "/Users/boksilhwang/Documents/test.py", line 7, in <module>
    print(obj.__age)
AttributeError: 'Student' object has no attribute '__age'

클래스 예제2. 프라이빗 변수, 학생 정보 클래스 만들기.

class Student :
    def __init__(self, name=None, age=0) :
        self.__name = name
        self.__age = age
        
    def getAge(self) :
        return self.__age

    def getName(self) :
        return self.__name

    def setAge(self, age) :
        if age < 0 :
            self.__age = 0
        else :
            self.__age = age

    def setName(self, name) :
        self.__name = name

obj = Student('Hong', 20)
name = obj.getName()
print(name)
obj.setAge(-21)
age = obj.getAge()
print(age)

#print(obj.age) # 불가능
print(obj.getAge()) # 가능

#print(obj.age)
#obj.age = -21
#print(obj.age)

#print(obj.getName())

클래스 예제3. 프라이빗 변수, 원을 클래스로 표현

import math
class Circle :
    def __init__(self, radius = 1.0) :
        self.__radius = radius

    def setRadius(self, r) :
        self.__radius = r

    def getRadius(self) :
        return self.__radius

    def calcArea(self) :
        area = math.pi * self.__radius * self.__radius
        return area

    def calcCircum(self) :
        circumference = 2.0 * math.pi * self.__radius
        return circumference

c1 =Circle(10)
print('원의 반지름 = ', c1.getRadius())
print('원의 넓이 = ', round(c1.calcArea(), 2))
print('원의 둘레 = ', round(c1.calcCircum(), 2))

c1.setRadius(5) #인수가 아닌 메소드로 변경
print(c1.getRadius(), c1.calcArea())

클래스 예제4. 프라이빗 변수, 강아지 이름과 나이 불러오기

class Dog :
    def __init__(self, name=None, age = 0) :
        self.__name = name
        self.__age = age

    def getName(self) :
        return self.__name

    def getAge(self) :
        return self.__age

    def setAge(self, age) :
        self.__age = age

coffee = Dog('Coffee', 12)
latte = Dog('Latte', 5)

print('{}의 나이는 {}살.'.format(coffee.getName(), coffee.getAge()))
print('{}의 나이는 {}살.'.format(latte.getName(), latte.getAge()))

latte.setAge(4)
print('{}의 나이는 {}살.'.format(latte.getName(), latte.getAge()))

Q. return이 그 값을 반환하고 보여주는게 아니구나? 반환된 값이 저장이 되는 건가? 반환 안 시키면 저장 안되고?

A. 프린트문이 어디에 있냐에 따라 다른 듯. print문이 클래스 내부의 함수 내부에 있으면 a.getAge() 할때 알아서 프린트 할꺼고, 리턴값 자체로는 전달용이지 보여주기 용이 아님. 그러니 보여주고 싶으면 내, 외부에서 프린트문을 사용해야 함.


객체 생성과 사용

✔️ 특수 메소드

__str__ 와 같이 언더바가 붙은 함수를 특수 메소드라 함.

✔️ __str__ 함수, 메소드 실행 시 자동 실행.

print(box) << 객체자체를 print문에 사용 시 __str__함수가 자동 실행 됨.
__str__ 에 출력하고자 하는 내용을 작성 해두면 좋다.

클래스 예제5. __str__을 사용해보자.

class Box :
    def __init__(self, width=0, length=0, height=0) :
        self.__width = width
        self.__length = length
        self.__height = height

    def setWidth(self, width) :
        self.__width = width

    def setLength(self, length) :
        self.__length = length

    def setHeight(self, height) :
        self.__height = height

    def getVolume(self) :
        return self.__width * self.__length * self.__height

    def __str__(self) :
        return '(%d, %d, %d)' % (self.__width, self.__length, self.__height)

box = Box(100, 100, 100)
print(box)
print('상자의 부피는 {}'.format(box.getVolume()))

=============================== RESTART: C:\Users\GIEC\Desktop\기초문법\1031\test.py ==============================
(100, 100, 100) #__str__의 결과 값
상자의 부피는 1000000

클래스 예제6. __str__을 사용해보자. 자동차 클래스 만들기

class Car :
    def __init__(self, speed=0, gear=1, color='White') :
        self.__speed = speed
        self.__gear = gear
        self.__color = color

    def setSpeed(self, speed) :
        self.__speed = speed

    def setGear(self, gear) :
        self.__gear = gear

    def setColor(self, color) :
        self.__color = color

    def __str__(self) :
        return '(Speed : {}, Gear : {}, Color : {})'.format(self.__speed, self.__gear, self.__color)
        #return '(%d, %d, %s)' % (self.__speed, self.__gear, self.__color) #%s의 활용성을 몰라서 .format을 사용함.

car = Car()
car.setSpeed(100)
car.setGear(3)
print(car)
car.setColor('Black')
print(car)

=============================== RESTART: C:\Users\GIEC\Desktop\기초문법\1031\test.py ==============================
(Speed : 100, Gear : 3, Color : White)
(Speed : 100, Gear : 3, Color : Black)

외부 변수 값을 가지고 클래스 내부 함수에서 값을 변경해도 외부 변수 값이 변경되는 것은 아니다.

✔️ 정적 변수 또는 클래스 변수

클래스 내에 모든 객체를 통틀어 하나만 생성하여 모든 객체가 이것을 공유, 이러한 변수를 정적 멤버 또는 클래스 멤버하고 한다.
클래스 내부에 있는 변수는 정적 변수(클래스 변수)
정적 변수는 클래스의 변수이므로 함수인 __init__ 위에 정의 한다.

class Television :
    serialNumber = 0 #클래스의 변수
    def __init__(self) :
        Television.serialNumber += 1 
        self.number = Television.serialNumber
        
tv1 = Television()
print(Television.serialNumber) 
#외부 변수가 아닌 클래스 변수이므로 `클래스.변수`로 출력할 수 있다.

tv2 = Television()
print(Television.serialNumber)


=============================== RESTART: C:\Users\GIEC\Desktop\기초문법\1031\test.py ==============================
1
2 #따라서 출력 값이 초기화 되지 않고 +1이 더해져 2가 나온다.
post-custom-banner

0개의 댓글