함수형 프로그래밍

  • 기능 단위로 작성
  • 유사한 동작을 하는 함수들은 파일로 묶어서 구분
  • 일반적으로 속도가 빠르고 불필요한 내용을 포함하지 않는 것이 장점
  • 빅데이터 처리 분야에서 많이 사용

 

객체 지향 프로그래밍

  • 유사한 동작을 하는 함수나 데이터를 하나로 묶어서 프로그래밍 하는 방식
  • 유사한 동작을 하는 함수와 데이터를 클래스라는 템플릿으로 묶고 템플릿을 이용해서 인스턴스를 생성해서 사용하는 방식으로 클래스도 하나의 인스턴스로 취급

 

 

 

클래스와 인스턴스

  • 인스턴스 만들기: 메모리에 인스턴스를 생성하고 인스턴스의 참조(id)를 리턴
  • 한번만 쓸거면  클래스이름(매개변수 나열...)
  • 여러번 쓸거면 obj = 클래스이름(매개변수 나열...)
  • 인스턴스를 생성하고 참조하는 데이터가 없다면 언제인지는 알 수 없지만 자동으로 메모리가 정리된다.
  • 일반적으로 클래스 이름은 대문자로 시작하고 Camel 표기법을 사용한다. 

 

 

1) 데이터(속성 - attribute)

클래스 속성: 클래스 안에 데이터를 만들고 클래스와 인스턴스가 공동으로 사용

  • 클래스 안에 변수를 만들면 이것은 클래스 속성이 된다. 

인스턴스 속성: 인스턴스 안에 만들어서 인스턴스만 사용할 수 있는 것

  • 메서드 안에서 메서드의 첫번째 매개변수이름.속성으로 만들면 이는 인스턴스 속성이 된다.

속성에 접근할 때는

  • 내부에서는 이름만으로 가능하지만
  • 외부에서는 클래스/인스턴스이름.속성으로 접근
#자동차를 표현하는 클래스
class Car:
    #클래스 속성 (클래스, 인스턴스 모두 접근, 공유)
    maker = "KIA"

#Car 클래스의 인스턴스를 생성
car = Car()

print(car.maker)
print(Car.maker)

 

 

 

2) 기능(메소드)

  • 클래스 안에 있는 함수: 메소드(Method)

 종류

  • 초기화 메소드(init): 인스턴스를 만들 때 호출되는 메소드로, 만들지 않아도 기본적으로 아무일도 하지 않는 초기화 메소드가 존재하며 다른초기화 메소드를 만들면 제거된다. 다른 언어에서는 생성자(Constructor)라고 한다.
  • 클래스 메소드, 스태틱 메소드: 클래스 안에 특별한 decorator와 함께 사용, 클래스와 인스턴스 모두 호출 가능한 메소드
    • 인스턴스 속성을 만들거나 소유할 수 없다.
    • 인스턴스 속성이 필요없는 동작을 하고자 할 때 사용
  • 인스턴스 메소드: 클래스 안에 만들어지는 함수로, 무조건 1개의 매개변수(객체 자신의 참조)를 가지고 만들어지는 함수로 인스턴스만 호출할 수 있고 인스턴스 속성 생성이 가능하다. 
    • 호출방법 
    • Bound 호출: 인스턴스.메소드(매개변수를 나열 - self 값을 대입하지 않음) - a1.add(a2)
    • Unbound 호출: 클래스.메소드(인스턴스, self를 제외한 매개변수를 나열) - Math.add(a1, a2)
  • 인스턴스 메소드 안에서 첫번째매개변수.속성이름 = 값의 형태로 만들면 인스턴스 속성이 만들어진다.
  • 이 속성은 인스턴스 이름으로 접근하고 인스턴스마다 별도로 만들어진다.
#바운드 호출
car.method()
#언바운드 호출
Car.method(car)

print(help(str.capitalize))
x = "hello"
print(x.capitalize())
print(str.capitalize(x))
  • 리턴이 없으면 원본 데이터 자체를 변경해주는 것이다. 
  • 리턴이 있으면 바꾼 데이터를 주는 것이다. 

 

class Singer:
    className = "가수"

#인스턴스 생성
singer1 = Singer()
singer2 = Singer()

#데이터 비교
print(singer1 == singer2)

#id 비교
print(singer1 is singer2)

#클래스 변수 확인
print(singer1.className)
print(singer1.className)

#동일한 데이터인지 비교
print(singer1.className is singer2.className)
print(id(singer1.className))
print(id(singer2.className))
  • 인스턴스는 자기 안에 값이 없으면 클래스를 쫓아감!
  • 그래서 인스턴스는 다르지만 데이터의 id는 같다. 같은 클래스 변수를 가르키고 있음.
class Singer:
    className = "가수"

    #인스턴수 변수를 생성하기 위한 인스턴스 메서드를 생성
    def create(self, name:str) -> None:
        #매개변수로 받은 데이터를 self.name에 대입
        self.name = name
        groupName = "에스파" #self 붙이지 않으면 함수 안에서 쓰는 지역변수기 때문에 밖에서 호출 불가능
 
    #좋은 예
    def setHometown(self, hometown):
        self.homtown = hometown
        
    #나쁜 예
    def setAttr(self, name, hometown):
        self.name = name
        self.homtown = hometown

#인스턴스 생성
singer1 = Singer()
singer2 = Singer()

#인스턴스 메서드 호출
singer1.create("조이") #바운드 호출
Singer.create(singer2, "아이린") #언바운드 호출

print(singer1.name) 
print(singer2.name)

조이

아이린

  • 매개변수 데이터가 많아지는 것은 나쁜 예

 

3) Accessor(getter와 setter, 접근자 메소드)

  • 수정 가능mutable한 변수를 동시작업할 때 제어하는 메소드
  • 인스턴스가 소유한 속성의 값을 수정하거나 읽기 위한 메소드

getter

  • 속성의 값을 읽는 메소드
  • 동시에 접근이 가능하다.
get속성이름(self):
    속성의 값을 리턴
  • 속성의 자료형이 bool인 경우 is속성이름(self)
  • 메소드 이름에서 [속성이름]의 첫글자는 대문자.

setter

  • 속성의 값을 수정하는 메소드
  • 동시에 접근하면 안된다.
set속성이름(self, 매개변수):
    매개변수로 받은 데이터를 속성에 대입
    (리턴 None)
  • 메소드 이름에서 [속성이름]의 첫글자는 대문자.
class Singer:
    
    #name이라는 속성의 accessor
    def setName(self, name):
        self.name = name
    
    #name의 getter
    def getName(self):
        return self.name

 

참고로 요즘에는 아래와 같이 짜야 한다!

class Singer:
    
    #name이라는 속성의 accessor
    def setName(self, name:str) -> None:
        self.name = name
    
    #name의 getter
    def getName(self) -> str:
        return self.name
        
#인스턴스 생성
singer1 = Singer()

#name 설정
singer1.setName(name = "민지")
print(singer1.getName())

민지

singer2 = Singer() #에러
print(singer2.getName())

AttributeError: 'Singer' object has no attribute 'name'

  • setter를 호출하지 않고 getter를 호출해서 에러
  • setter를 항상 먼저 불러야 한다. 변수를 먼저 생성해야 하니까!
  • 혹은 인스턴스가 만들어질 때부터 변수가 있도록 하는 방법이 있다. 그게 __init__ !

 

파이썬의 메소드 이름 관습

  • 첫글자를 대문자로 사용해야 하는 경우 _로 시작
    • 소문자로 시작하기도 한다.
  • _ _뭐시기: 직접 접근 불가 메소드 (private)
  • _ _뭐시기 _ _: 직접 호출 불가, 다른 방법으로 호출해야 함.
...
    def __str__(self): #출력하는 메소드에 인스턴트를 넣으면 자동으로 출력한다.
        print("나의 이름은 ", self.name) #나의 이름은 민지
        return self.name
...

#name 설정
singer1.setName(name = "민지")
print(singer1) #민지

나의 이름은  민지

민지

 

 

4) 초기화 메서드와 소멸될 때 호출되는 메서드

생성자

  • 객체가 생성될 때 자동으로 실행, 메모리를 할당한다.
  • 그리고 멤버변수 값을 초기화하는 역할을 한다. 
  • 만약 초기화 작업이 필요 없다면 클래스 설계 시 생성자를 생략할 수 있다. (파이썬은 기본생성자를 자동 제공)
더보기

예문

#(1) 생성자 이용 멤버변수 초기화
class Multiply :
    #멤버 변수
    x = y = 0
    
    #생성자 : 초기화
    def __init__(self, x, y): #객체만 생성
        self.x = x
        self.y = y
    
    #메서드
    def mul(self):
        return self.x * self.y
    
obj = Multiply(10, 20) #생성자
print('곱셈=', obj.mul()) #곱셈=200

 

#(2) 메서드 이용 멤버변수 초기화
class multiply2 :
    #멤버 변수
    x = y = 0
    
    #생성자 없음 : 기본 생성자 제공
    def __init__(self):
        pass
    
    #메서드: 멤버변수 초기화
    def data(self, x, y):
        self.x = x
        self.y = y
    
    #메서드: 곱셈
    def mul(self):
        return self.x * self.y

obj = Multiply() #기본 생성자
obj.data(10, 20) #동적 멤버변수 생성
print('곱셈=', obj.mul()) #곱셈=200

 

더보기

self가 뭐야?

  • 클래스의 생성자와 메서드는 기본적으로 self라는 매개변수를 갖는다.
  • 클래스를 구성하는 멤버들 즉 멤버변수와 메서드를 호출하는 역할을 한다.
  • 예를 들어 생성자 안에서 멤버변수 값을 초기화하거나 메서드 안에서 멤버변수를 참조하거나 또는 다른 메서드를 호출할 경우 이용한다.
class multiply3:
    #멤버변수 없음
    #생성자 없음
    
    #동적 멤버변수 생성/초기화
    def data(self, x, y):
        self.x = x #동적으로 멤버변수가 만들어지고 매개변수에 의해서 값이 초기화된다.
        self.y = y
        
#곱셈연산
def mul(self):
    result = self.x * self.y
    self.display(result) #메서드 호출

#결과 출력
def display(self, result):
    print("곱셈= %d" %(result) ) #곱셈 = 200
    
obj = multiply3() #기본 생성자
obj.data(10, 20)
obj.mul()

 

 

초기화 메소드 __init__

  • 인스턴스를 만들 때 호출하는 메소드
  • 생성자와 다른 점, 메모리 할당을 하지 않는다!
  • 기본적으로 매개변수가 self 1개인 메소드가 제공된다. 
    • 기본적으로 제공되는 __init__은 아무일도 하지 않는다.
    • 무엇인가를 하도록 하려면 __init__을 재정의(overriding) 해야 한다. 
    • 직접 재정의를 하면 기본 제공되는 메소드는 없어진다. 
  • 인스턴스가 생성될 때 인스턴스 속성(attribute)을 초기화할 때 주로 사용
  • 외부에서 만든 데이터를 인스턴스 속성에 대입하는 작업을 Injection(주입)이라고 한다.
    ex. singer1.setName(name = "민지")
class Singer:
    
    def setName(self, name:str) -> None:
        self.name = name
    
    def getName(self) -> str:
        return self.name
    
    #초기화 메소드
    def __init__(self, name):
        self.name = name
        
 
singer1 = Singer() #에러발생
print(singer1.getName())

TypeError: Singer.__init__() missing 1 required positional argument: 'name'

  • name에 초기값을 줘야 함!
class Singer:
    
    def __init__(self, name = "noname"):
        self.name = name
  
 ...
  • 이제 초기값이 정의됐기 때문에 값을 주든 안주든 에러가 안난다.

 

소멸 메소드 __del__

  • 인스턴스가 소멸될 때 호출되는 메소드
  • 객체 사용이 완료되면 자동으로 실행되어 객체를 메모리에서 소멸시키는 역할을 한다.
__del__(self):
    내용
class Singer:
    
    #name이라는 속성의 accessor
    def setName(self, name):
        self.name = name
    
    #name의 getter
    def getName(self):
        return self.name
    
    #초기화 메소드
    def __init__(self, name = "noname"):
        self.name = name
    
    def __del__(self):
        print(self, "메모리 해제")        
 
singer1 = Singer() 
print(singer1) #<id>
singer1 = None 
#<id> 메모리 해제
singer1 = Singer() 
singer3 = singer1
singer1 = None
  • singer1이 가리키던 인스턴스를 해제(None을 가리키도록 설정 → 메모리 해제 대상)
  • 그러나 singer3도 이제 Singer()를 가리키기 떄문에 사실은 reference count = 1인 상태!
  • python은 reference count = 0이 될 때 메모리가 해제

인스턴스의 reference count = 0 이 되면 호출

  • 외부의 데이터를 사용하는 경우 무조건 정리를 하고자 할때 주로 사용
  • 생성자의 반대역할 
  • 하지만 파이썬 자체에서 메모리 관리를 자동으로 해주기 때문에 많이 사용되지는 않는다.

 

5) 클래스가 인스턴스 없이 호출할 수 있는 메소드 

static 메소드

  • self 없이 클래스 안에 만들 수 있는 메소드
  • 이 메소드는 클래스가 인스턴스 없이 호출할 수 있고 인스턴스를 이용해서 호출할 수도 있다.
@staticmethod
def 이름(self제외 매개변수):
    내용
  • 파이썬에서 @로 시작하는 단어는 decorator라고 하는데 코드를 하나의 단어로 작성하고자 할 때 사용
  • 이 코드는 메소드의 내용이 수행되기 전이나 수행된 후에 하고자 하는 작업에 대한 코드(Filter, AoP)

        *AoP 관점지향적 프로그래밍

        *JAVA에서는 Class method만 사용한다. (@Classmethod)

 

Heap 자료구조 Stack 자료구조
영구적 할당
Static: Class, Function, Literal


반영구적 할당
Dynamic: Instance
Function Call, 임시 영역
- LIFO구조 (Last In First Out)

 

  • 사용자는 Class에 접근하거나, stack을 통해서 Instance에 접근할 수 있다. 
  • Class에 있는 instance method를 사용하려면 singer = Singer()의 과정이 필요하지만
  • Class에 있는 static method를 사용하려면 바로 Class에 접근해서 사용하면 속도와 메모리 효율이 좋다.
  • 따라서 self가 없는 애들은 static으로 만드는게 좋다. 

@staticmethod

class Singer():
    #인스턴스 없이 클래스가 호출할 수 있는 메서드
    @staticmethod
    def staticMethodExam():
        print("static method")
    
    #클래스에 대한 정보를 갖는 매개변수 1개가 필수    
    @classmethod
    def classMethodExam(cls):
        print("class method")
            
#instance = Singer()
#instance.staticMethodExam()

Singer.staticMethodExam()
Singer.classMethodExam()

 

 

 

6) Inheritance(상속)

상속

  • 하위 클래스가 상위 클래스의 모든 것을 물려받는 것

        * 객체지향언어에서는 is a로 사용하기도 함

  • 여러 개의 클래스들에 공통된 내용이 있는 경우 공통 내용을 상위 클래스에 만들고 상속을 받는 방법으로 대체한다.
    • a = 10 변수를 설정해서 나중에 값을 수정할 때 변수만 수정하면 되는 맥락과 같음!
  • 객체지향 프로그래밍의 기본 원칙에서는 여러 하위 클래스에 공통으로 존재하는 기능을 상위 클래스로 올려보내는 것으로 간주한다.
상위 클래스
        ↑
하위 클래스

*그러니 부모클래스, 자식클래스라는 말은 절대 쓰지 말자!

 

단일 상속: 하나의 클래스로부터 상속받는다.

다중 상속: 여러 개의 클래스로부터 상속받는다. 파이썬은 다중 상속을 지원

 

목적

  • 여러 클래스의 공통된 내용이 존재해서 - 일반 프로그래밍
  • 제공되는 클래스의 기능이 부족해서 - 프레임워크
    • 프로그램을 여러개 만들면 공통적으로 사용하는 기능이 있다. 이런 공통 기능을 미리 만들어서 제공하기도 한다.
    • 이 경우는 클래스의 기능이 부족할 때 확장하기 위해서 상속을 하는 것
  • 공통된 인터페이스를 사용하기 위해서 - 다형성 구현

구현

class 클래스이름(상위클래스 이름 나열)
class Phone:
    def superMethod(self):
        print("phone 클래스의 메소드")

#다중상속받은 클래스
class Camera:
    def superMethod(self):
        print("Camera 클래스의 메소드")

#상속받은 클래스
class SmartPhone(Phone, Camera): #Camera가 Phone보다 먼저 오면 Camera superMethod 호출
    def subMethod(self):
        print("Smartphone 클래스의 메서드")


subOnj = SmartPhone()
subOnj.subMethod()
#SmartPhone 클래스는 phone 클래스를 상속받았으므로 phone 클래스의 멤버를 사용 가능
subOnj.superMethod()

Smartphone 클래스의 메서드
Camera 클래스의 메소드

 

상위 클래스의 __init__ 호출

  • 파이썬에서 하위 클래스의 __init__ 메소드에서 상위 클래스의 __init__를 자동으로 호출하지 않는다.
  • 대다수의 객체 지향 언어에서 상속을 받으면 하위 클래스의 생성자에서 상위 클래스의 생성자를 자동으로 호출한다.
  • 하위 클래스의 __init__ 안에서 상위 클래스의 초기화 메소드를 호출하고자 하는 경우는 super().__init__()를 호출
class Phone:
    def __init__(self):
        self.name = "전화기"
    
    def superMethod(self):
        print("phone 클래스의 메소드")

#상속받은 클래스
class SmartPhone(Phone):
    def __init__(self):
        #상위 클래스의 속성을 자동으로 호출하지 않기 떄문에 생성자라고 할 수 없음
        #상위 클래스의 __init__을 호출해줘야 한다.
        super().__init__()
        print(self.name)
    
    def subMethod(self):
        print("Smartphone 클래스의 메서드")

subOnj = SmartPhone()
subOnj.subMethod()
subOnj.superMethod()

 

 

 

7) Method Overriding

method overloading(중복 정의)

하나의 클래스에 동일한 이름이지만 매개변수의 개수나 자료형이 다르게 만들어진 메소드가 존재하는 경우

method overriding(재정의)

상위 클래스(내용이 있음)에 존재하는 메소드를 하위 클래스에서 다시 정의하는 것

 

목적

기능 확장 ★

  • 기능을 10개 주는데, 클래스가 확장이 되는게 아니라 메소드가 확장이 됐으면 좋겠다. 새로 만들면 이름이 바뀐다. 기존의 이름을 쓰되 다른 기능을 추가해주는 것을 오버라이딩이라고 한다. 
  • 오버라이딩을 하면 상황에 따라서 같은 이름이 다른 일을 한다. 
    • 똑같은 클릭인데 탐색기에서는 선택, 버튼에서는 하이퍼링크 따라가기. 
    • 어차피 같은 동작인데 여기서는 클릭, 여기서는 프레스라고 하면 스트레스니까..!

언어에서는 상위 클래스의 메서드를 호출하지 않는 것이 에러가 아니지만 프레임워크에서는 에러가 발생한다.

class Phone:
    def __init__(self):
        self.name = "전화기"
    
    def superMethod(self):
        print("phone 클래스의 메소드")

#상속받은 클래스
class SmartPhone(Phone):
    def __init__(self):
        super().__init__()
        print(self.name)
    
    #상위클래스에 존재하는 메소드를 하위 클래스에서 다시 구현
    #메소드 오버라이딩
    def superMethod(self):
        super().superMethod() #기능 확장, 순서 중요
        print("SmartPhone 클래스의 메소드")
    
    def subMethod(self):
        print("Smartphone 클래스의 메서드")

subOnj = SmartPhone()
subOnj.subMethod()
subOnj.superMethod()
  • 만들 때는 상위클래스부터, 지울 때(destroy, close)는 하위클래스부터! 
  • 대부분은 super()를 먼저 쓰지만, 파괴할 때는 super()가 뒤에 온다. 

 

 

8) Abstract(추상)

Abstract Class(추상 클래스)

  • 인스턴스를 만들 수 없는 클래스
  • 상속을 통해서만 사용하는 클래스

만드는 방법

import abc 
class 클래스이름(metaclass=abc.ABCMeta)
  • import는 파이썬 기본 모듈이 아닌 파일의 내용을 현재 프로그램에 가져올 때 사용하는 명령어
  • import abc는 abc.py라는 파일의 내용을 abc라는 이름으로 묶어서 가져오는 것이다. 
  • import abc as X: abc.py라는 파일의 내용을 X라는 이름으로 묶어서 가져오는 것이다. 

 

Abstract method (추상 메소드)

  • 내용이 없는 메소드
  • 반드시 추상 클래스에 존재
  • 하위 클래스에서 반드시 구현해야 하는 메소드

        *자바에서는 이것도 오버라이딩이라고 한다. 하지만 오버라이딩의 목적은 기능확장이니까, 정확히는 implements(구현)이라고 해야 한다.

 

생성 방법

@abc.abstractmethod
def 이름(매개변수):
    pass

 

사용 이유

  • 동일한 인터페이스를 제공하기 위해서!
  • 인터페이스는 프로토콜이라고도 한다. (규칙, 약속)
    • 음식점의 키오스크에는 내용물은 없고 이름하고 그림만 있다. 하지만 반드시 이 음식점에서 해줄 수 있어야 한다. 이 키오스크가 음식점과 대화하기 위한 인터페이스. 
    • 인터페이스를 만드는 이유는 고객과 소통하는 템플릿을 만들기 위해서다.
#추상 클래스를 만들기 위한 모듈
import abc

class Phone(metaclass=abc.ABCMeta):
    #추상 메소드
    @abc.abstractmethod
    def call(self):
        pass    

#추상 클래스를 상속받은 클래스
#추상 메소드를 반드시 구현
class SmartPhone(Phone):
    pass

smartPhone = SmartPhone()

TypeError: Can't instantiate abstract class SmartPhone with abstract method call

class SmartPhone(Phone):
    def call(self):
        print("성공")

SmartPhone = SmartPhone()
print(smartPhone.call())

성공

None

 

템플릿 메서드 패턴

  • 추상 메서드를 소유한 추상 클래스(인터페이스, 프로토콜)를 만들고 이를 구현한 클래스를 만들어서 
  • 고객의 요구를 처리하는 클래스 생성
#추상 클래스를 만들기 위한 모듈

import abc

class InsertService(metaclass=abc.ABCMeta):
    #추상 메소드
    @abc.abstractmethod
    def insert(self, data) -> bool:
        pass    

class InsertServiceImpl(InsertService):
    #대략적인 동작하는 코드를 작성하고 테스트 한 후 실제 코드를 구현하는 방식이 TDD
    def insert(self, data) -> bool:
        print("데이터 추가")
        return True

service = InsertServiceImpl()
print(service.insert("데이터"))

데이터 추가

True

 

 

 

9) Polymorphism(다형성)

  • 동일한 메시지에 대하여 다르게 반응하는 성질
  • 동일한 코드가 호출하는 인스턴스에 따라 다른 메소드를 호출하는 것
  • 상속과 오버라이딩을 이용해서 구현
import abc

class Starcraft(metaclass=abc.ABCMeta):
    #추상 메소드
    @abc.abstractclassmethod
    def attack(self, data) -> None:
        pass
    
class Protoss(Starcraft):
    def attack(self, data) -> None:
        print("프로토스 ", data, " 공격")
    
class Terran(Starcraft):
    def attack(self, data) -> None:
        print("테란 ", data, " 공격")
        
star = Protoss()
star.attack("드래군")
star = Terran()
star.attack("종이비행기")

프로토스  드래군  공격
테란  종이비행기  공격

  • 유사한 동작은 하나의 인터페이스로 동작이 되어야 한다.
  • 프로토스든 테란이든 단축키를 하나로! 

        * 프로그레시브 웹앱: 스마트폰과 웹에서 동일한 UI로 만들자. 그럼 배울 동작이 하나라 간편 (유튜브)

 

 

 

 

 

 

 

더보기

클래스와 객체 추가

 

클래스와 객체

클래스(Class)

  • 변수와 함수들을 하나로 묶어놓은 논리적 집합체
  • 속성(Attribute)와 행위(Action)로 구성된다. 
  • 클래스의 구성요소를 UML 표기법으로 도식화하면
  • 설계 도면은 필요한 속성만 정의해두지만, 클래스에는 자동차가 할 수 있는 동작도 정의해야 한다. 
  • 클래스의 속성은 자료(data)를 나타낸다. (변수, 필드의 개념)
  • 클래스의 행위는 자료를 연산하거나 조작하는 역할을 한다. (메소드, 함수의 개념) 
    • 함수(Function): 독립된 기능을 수행하는 코드(명령문)들의 집합
    • 메서드(Method): 클래스에 포함되어 있는 함수

* 클래스 변수는 객체를 생성하지 않아도 쓸 수 있는 광역변수

 

객체(Object)

  • 클래스에 의해서 만들어지는 결과물(instance)
  • 클래스를 선언해야 객채를 생성할 수 있다. 
    • 함수: 정의 → 호출
    • 클래스: 클래스 정의 → 객체 생성 → 멤버 호출
  • 클래스를 만들었으나 객체를 생성하지 않으면 클래스의 멤버(변수, 메소드)를 쓸 수 없다.
    • 멤버변수 = (클래스변수, 객체변수, 종단변수)
    • 클래스변수는 정적변수/전역변수, 객체변수는 동적변수
    • 클래스 변수가 객체변수보다 우선순위에 있기 때문에 클래스 변수는 객체 생성 없이도 사용할 수 있다.
  • 각 객체는 서로 독립적인 메모리 주소를 가지고 있으며, 메시지(Message)를 이용해서 상호작용도 가능하다.

 

# 함수 형식
def 외부함수(매개변수) :
    변수선언
    def 내부함수() :
        명령문
        return 값
    return 내부함수
    
# 클래스 형식
class 클래스명:
	변수 선언
    def 생성자() :
    	명령문
    def 함수명() :
    	명령문

* 생성자도 메서드의 일부로 보는게 편하다. 

# (1)함수 정의
def calc_func(a, b) : #외부함수
    #변수 선언: 자료저장
    x = a #10
    y = b #20
    
    def plus(): #내부함수
        p = x + y
        return p
    
    def minus(): #내부함수
        m = x - y
        return m
    
    return plus, minus #내부함수는 괄호 없이 호출

# (2)함수 호출
p, m = calc_func(10, 20)
print('plus =', p())
print('minus=', m())


# (3)클래스 정의
class Calc_class :
    #클래스 변수: 자료저장
    x = y = 0
    
    # 생성자: 객체 생성 + 멤버변수 초기화 (__생성자__)
    def __init__(self, a, b): #self는 26번의 x, y를 의미한다.
        self.x = a #10
        self.y = b #20
        
    #클래스 함수
    def plus(self):
        p = self.x + self.y #변수선언
        return p
    
    #클래스 함수
    def minus(self):
        m = self.x - self.y
        return m
    
# (4)객체 생성
obj = calc_class(10, 20) #객체를 만드는 문장이 실행될 때, 생성자는 자동으로 실행된다.

# (5)멤버 호출
print('plus=', obj.plus()) #plus = 30
print('minus=', obj.minus()) #minus = -10

 

객체와 인스턴스의 차이

인스턴스는 개념적으로 객체와  비교했을 때, 현재 가장 최근에 만들어진 객체를 의미한다.

 

 

클래스의 구성요소

클래스 구성요소: 멤버(Member) + 생성자(Constructor)

               멤버번수(자료) + 메서드(기능)

 

class Car:
    #(1) 멤버변수
    cc = 0 #엔진 cc
    door = 0 #문짝 개수
    carType = None #null
    
    #(2) 생성자
    def __init__(self, cc, door, carType):
        #멤버 변수 초기화
        self.cc = cc
        self.door = door
        self.carType = carType #승용차, SUV
    
    #(3) 메서드
    def display(self):
        print("자동차는 %d cc이고, 문짝은 %d개, 타입은 %s"
              %(self.cc, self.door, self.carType))
    
#(4) 객체 생성
car1 = Car(2000, 4, "승용차") #객체 생성 + 초기화
car2 = Car(3000, 5, "SUV")
    
#(5) 멤버 호출 : object.member()
car1.display() #car1 멤버 호출
car2.display() #car2 멤버 호출

 

(1) 멤버변수

Car 클래스의 선언부에 3개의 멤버변수(cc, door, carType)를 선언한다. 

 

(2) 생성자

생성자는 함수의 선언과 유사하지만 차이점은 이름이 정해져 있고 self라는 매개변수를 사용한다는 점이다.

예문에서 생성자는 def 명령어 다음에 '__init__'이라는 이름과 self라는 매개변수를 이용하여 선언된다.

self 매개변수는 생성자 내에서 클래스의 멤버를 호출하는 데 이용된다.

self 매개변수 다음에 오는 3개의 매개변수는 3개의 멤버변수 (cc, door, carType)에 값을 초기화하기 위한 매개변수다.

매개변수는 객체가 생성 시의 인수를 받아서 멤버변수에 초기화하는 역할을 한다.

 

(3) 메서드

메서드는 함수 선언과 동일하다. 차이점은 생성자와 마찬가지로 self라는 정해진 매개변수를 포함하고 있다는 점이다.

예문에서 display() 메서드는 self를 이용하여 3개의 멤버변수의 내용을 출력하는 역할을 한다. 

 

(4) 객체 생성

클래스의 생성자를 이용하여 객체를 생성한다.한 개의 클래스에 의해서 다수의 객체를 만들어낼 수 있다.

Car 클래스의 생성자를 이용하여 객체를 생성하는 방법은 참조변수 = Car(인수)

Car()는 Car 클래스의 생성자이고, 인수는 생성자의 매개변수에 전달할 실제값이다.

따라서 Car(2000, 4, "승용차") 형식의 명령문은 3개의 멤버변수에 각각 cc=2000, door=4, carType="승용차"가 할당되어 car1 객체가 생성된다.

 

(5) 멤버 호출

생성된 객체의 참조변수를 이용하여 객체의 멤버를 호출할 수 있다.  참조변수.멤버(멤버변수 or 메서드)

 

'Python' 카테고리의 다른 글

Day8. 가상환경 만들기  (1) 2024.01.19
Day7. 웹프로그래밍 개요  (1) 2024.01.18
Day5. 함수  (1) 2024.01.08
Day4. 딕셔너리와 반복문  (1) 2024.01.05
Day3. 조건문과 리스트  (2) 2024.01.04