Python: Class (클래스)

dev-swd·2020년 10월 27일
0

python

목록 보기
12/23
post-thumbnail

Python: 클래스


클래스 만들기

class Car:
    def __init__(self, maker, model, horse_power):
        self.maker       = maker
        self.model       = model
        self.horse_power = horse_power
    
    def start_up(self, key, fuel)
    	pass
    
    def go(self, speed, direction):
    	pass

my_car = Car("Bentz", "좋은 모델", "5000")

빈 클래스 만들기

class Car:
	pass

메서드 호출하기

# 위의 코드를 기준으로
my_car.go(20, "left")

메서드 안에서 메서드 호출하기

class Car:
    def __init__(self, maker, model, horse_power):
        self.maker       = maker
        self.model       = model
        self.horse_power = horse_power
    
    def start_up(self, key, fuel)
    	pass
    
    def go(self, speed, direction):
    	self.start_up(10, "backward")
    	pass

my_car = Car("Bentz", "좋은 모델", "5000")
  • 메서드 안에서 메서드를 호출할 때는 반드시 self.method() 형식으로 호출해야 한다.
  • self 없이 호출한다면 바깥쪽의 함수를 호출한다는 뜻이 된다.

특정 클래스인지 확인하기

isinstance(instance, class) >> True, False


__init__

  • 클래스가 실체화 될 때 자동으로 호출. (인스턴스를 만들 때 호출되는 special method)
    즉, __init__ 이라는 이름 그대로 인스턴스(객체)를 초기화한다.
  • self 파라미터는 클래스가 실체화된 객체를 넘겨주어야 하며, 파이썬이 자동으로 넘겨준다.
  • self 파라미터는 항상 정의되어야 있어야 하며 맨 처음 파라미터로 정의 되어야 한다. (그래야 파이썬이 알아서 넘겨줄 수 있으므로)

앞 뒤로 __ 가 붙은 메서드는 파이썬이 자동으로 호출해주는 메서드인데, 스페셜 메서드(special method) 또는 매직 메서드(magic method)라고 부른다.


self

self 는 인스턴스 자기 자신을 의미한다. 인스턴스가 생성된 후, 인스턴스를 사용하여 메서드를 호출하면, 현재 인스턴스가 자동으로 매개변수 self 로 들어온다.

class Person:
	# james = Person() 이 self 로 들어옴
	def __init__(self):
    	self.hello = "hi"
	
    # james.greeting() 이 self 로 들어옴
    def greeting(self):
    	print(self.hello)

james = Person()
james.greeting()

코드 출처: 코딩도장 파이썬 (https://dojang.io/mod/page/view.php?id=2373)

인스턴스 만들 때 값 받기

class class_name:
	def __init__(self, 매개변수1, 매개변수2):
    	self.속성1 = 매개변수1
        self.속성2 = 매개변수2
  • __init__ 메서드에서 self 다음에 값을 받을 매개변수를 지정한다. 그리고 매개변수를 self.속성에 넣어준다.
  1. 파이썬은 클래스 안에서 init 메서드를 한 번 밖에서 선언하지 못한다.
  2. init 메서드에 매개변수를 지정하면, 인스턴스를 생성할 때 반드시 값을 넣어줘야 한다.
  3. 빈 생성자와 같은 형태를 만드려면 init 메서드에 매개변수를 지정하지 않으면 된다 (추후 수정 할 수 있음)

클래스 위치 인수, 키워드 인수

클래스로 인스턴스를 만들 때 위치 인수와 키워드 인수를 사용할 수 있는데, 위치 인수와 리스트 언패킹을 사용하려면 *args 를 사용하고 args[0], args[1], args[2] 의 형태로 사용하면 된다.

class Wecoder:
	def __init__(self, *args):
    	self.name = args[0]
        self.group_number = args[1]
        
aaa = Wecoder(*['asdf', '14기'])

키워드 인수와 딕셔너리 언패킹을 사용하려면 다음과 같이 **kwargs를 사용하면 된다.

class Wecoder:
	def __init__(self, **kwargs):
    	self.name = args["name"]
        self.group_number = args["group_number"]
        
aaa = Wecoder(name="asdf", group_number="14기")
aaa = Wecoder({"name":"asdf", "group_number":"14기"})

인스턴스를 생성한 뒤에 속성을 추가할 수 있다.

class Wecoder:
	pass
        
aaa = Wecoder()    # 인스턴스 생성
aaa.name = "asdf"  # 인스턴스를 만든 뒤 속성 추가

다만, 이러한 방식으로 추가한 속성은 해당 인스턴스에만 해당 된다. 클래스로 다른 인스턴스를 생성한다면 추가한 속성은 생성되지 않는다.
인스턴스는 생성한 뒤에 속성을 추가할 수 있으므로, __init__ 메서드가 아닌 다른 메서드에서도 속성을 추가할 수 있다.
자유롭게 속성을 추가할 수 있지만, 특정 속성만 허용하고 다른 속성은 제한하고 싶을 수 있다. 이럴 때 __slot__ 을 사용한다.

class Person:
	__slot__ = ["name", "group_number"]

비공개 속성 (private)

class 클래스이름:
    def __init__(self, 매개변수)
        self.__속성 = 값
        self.__속성__ (xxxxx 이건 안됨)
  • __ 로 시작하는 속성은 private 속성을 부여받아, 클래스 바깥에서 instance.속성 으로 접근할 수 없다. (에러 발생: AttributeError: 'OOO' object has no attribute '속성 이름'

  • 비공개 속성은 클래스 안의 메서드에서만 접근할 수 있다.

  • 비공개 속성은 클래스 바깥으로 드러내고 싶지 않은 중요한 값이며, 바깥에서 함부로 바꾸면 안될 때 사용한다. (비공개 속성을 바꾸는 경우는 클래스의 메서드로 한정한다.)


비공개 메서드

class 클래스이름:
    def __init__(self, 매개변수):
        self.__속성 =def hello(self, 매개변수):
		self.__call_name()

	def __call_name(self, 매개변수):
    	print(매개변수, end="")

클래스 속성

  • __init__ 메서드에서 만들었던 속성은 인스턴스 속성입니다.
  • 클래스 속성은 아래와 같은 형태가 된다.
class 클래스이름:
    속성 =def __init__(self):
    	
  • 클래스 속성은 클래스에 속해 있으며 모든 인스턴스에서 공유한다.
  • 메서드에서 클래스 속성에 접근할 때는 self 도 가능하지만, self는 인스턴스를 뜻하므로 클래스 속성을 지칭하기에는 모호하다. 따라서 클래스 자체의 이름을 사용한다.
class Person:
    bag = []
 
    def put_bag(self, stuff):
        Person.bag.append(stuff)

print(Person.bag)
  • 마찬가지로 클래스 바깥에서도, 클래스 이름으로 클래스 속성에 접근한다.

클래스 내부의 속성 정리

  • __init__ 함수 안에 들어가있는 self.속성은 인스턴스 속성 이라고 한다.
  • 클래스 바로 밑에 정의한 속성은 클래스 속성 이라고 한다.
  • 인스턴스 속성은 각 인스턴스 고유의 속성이다.
  • 클래스 속성은 모든 생성된 모든 인스턴스에서 공유한다.
  • 클래스 속성은 클래스이름.속성 과 같은 형태로 접근하는 것을 약속으로 한다.
  • __ 를 이용하여 private 속성을 만든다.
  • private 속성은 바깥에서 접근할 수 없고, 오직 클래스 내부의 메서드에서만 접근 가능하다.
  • __dict__ 메서드로 속성을 출력해볼 수 있다.
  • instance.__dict__
  • class.__dict__

정적 메서드

  • 메서드 위에 @staticmethod
  • 정적 메서드는 매개변수에 self를 지정하지 않는다.
  • 정적 메서드는 클래스에서 바로 호출 가능하다. (클래스이름.정적메서드())
class Person:
    @staticmethod
    def hello():
    	print("hello,")

Person.hello()
  • 정적 메서드는 메서드의 실행이 외부 상태에 영향을 끼치지 않는 순수 함수(pure function)을 만들 때 사용한다.
  • 순수 함수는 언제나 같은 출력 값을 반환한다.
  • 즉, 인스턴스의 상태를 변화시키지 않는 메서드를 만들 때 사용하는 것이 정적 메서드.
  • 다시 말하면, 인스턴스 내용과는 상관없이 결과만 구하면 될 때 정적 메서드 사용.

클래스 메서드

  • 메서드 위에 @classmethod 를 붙인다.
  • 클래스 메서드는 첫 번째 매개변수에 cls를 지정해야 한다.
  • cls 에는 현재 클래스가 들어온다. 따라서 cls 로 클래스 속성에 접근할 수 있다.
class 클래스이름:
    @classmethod
    def 메서드(cls, 매개변수1, 매개변수2):
        코드
  • 클래스 메서드는 정적 메서드와 같이 인스턴스 없이 호출할 수 있다.
  • 클래스 메서드는 메서드 안에서 클래스 속성, 클래스 메서드에 접근해야 할 때 사용한다.
  • cls 를 사용하면 메서드 안에서 현재 클래스의 인스턴스를 만들 수도 있다.
  • cls() 는 클래스이름 과 같다.

정적 메서드 사용 예

class Date:
    @staticmethod
    def is_date_valid(date_string):
    	year, month, day = map(int, date_string.split('-'))
        return month <= 12 and day <= 31
#-
if Date.is_date_valid('2000-10-31'):
    print('올바른 날짜 형식입니다.')
else:
    print('잘못된 날짜 형식입니다.')

클래스 메서드 사용 예

class Time:
    def __init__(self, hour, minute, second):
        self.hour = hour
        self.minute = minute
        self.second = second
#
    @staticmethod
    def is_time_valid(time_string):
      time = list(map(int, time_string.split(":")))
      return time[0] <= 24 and time[1] <= 59 and time[2] <= 60
#
    @classmethod
    def from_string(cls, time_string):
      time = list(map(int, time_string.split(":")))
      return cls(time[0], time[1], time[2])
#
time_string = input()
#
if Time.is_time_valid(time_string):
    t = Time.from_string(time_string)
    print(t.hour, t.minute, t.second)
else:
    print('잘못된 시간 형식입니다.')

상속

class 부모 클래스:
	pass
    
class 자식 클래스(부모 클래스):
	pass
  • 연관되면서 동등한 기능일 때 사용한다.
  • 상속 관계를 확인할 때: issubclass()

자식 클래스에서 부모 클래스의 속성 사용하기

  • 자식 클래스라고 해서 무조껀 부모 클래스의 속성을 사용할 수 있는 것은 아니다.
  • 부모 클래스의 __init__() 메서드가 호출되어야 사용할 수 있다.
  • 부모 클래스의 __init__() 메서드를 호출하기 위해서 super() 를 사용하여, 부모 클래스를 초기화 해준다.
class Person:
    def __init__(self):
        print('Person __init__')
        self.hello = '안녕하세요.'
 
class Student(Person):
    def __init__(self):
        print('Student __init__')
        super().__init__() # super()로 기반 클래스의 __init__ 메서드 호출
        self.school = '파이썬 코딩 도장
  • 하지만 만약 자식 클래스에서 __init 메서드를 생략한다면, 부모 클래스의 __init() 이 자동으로 호출되므로, super() 는 사용하지 않아도 된다.
  • super(부모 클래스, self).__init__() 이와 같은 식으로 더 명확하게 super() 를 사용할 수 있다.

메서드 오버라이딩(overriding)

  • 자식 클래스의 메서드에서 super().메서드명() 으로 부모 클래스의 메서드를 호출하면, 원래의 기능을 유지하면서 새로운 기능을 덧붙일 수 있다.
  • 자식 클래스에서 부모 클래스의 메서드명과 같은 메서드를 만들면, 오버라이드 할 수 있다.
  • 물론 자식 클래스에서 부모 클래스의 메서드를 사용할 수 있다.

메서드 탐색 순서 확인하기

클래스.mro()


object 클래스

파이썬 3에서 모든 클래스는 object 클래스를 상속받으므로 기본적으로 object를 생략한다.

class X:
	pass
    
class X(object):
	pass
  • 위의 두 코드는 똑같은 의미이다.

추상 클래스(abstract class)


메서드의 목록만 가진 클래스이며 상속받는 클래스에서 메서드 구현을 강제하기 위해 사용된다.


from abc import *
 
class 추상클래스이름(metaclass=ABCMeta):
    @abstractmethod
    def 메서드이름(self):
        pass
  • 추상 클래스는 인스턴스로 만들 수 없다.
  • 추상 클래스는 인스턴스로 만들 수 없기 때문에, 추상 메서드도 호출할 일이 없다. 따라서 추상 클래스의 메서드는 모두 빈 메서드의 형태로 만든다.

36.8 연습문제: 리스트에 기능 추가하기
https://dojang.io/mod/page/view.php?id=2391

위 링크를 보고 기억 안날 때 마다 찾아보기
내용은 list 클래스를 상속받아서 replace 함수를 오버라이딩하는 내용이다.


다중 상속

업데이트 예정

profile
개발을 취미로 할 수 있는 그 때 까지

0개의 댓글