뮤트 개발일지

[파이썬 코딩 도장] Unit 34. 클래스 사용하기 본문

코딩도장

[파이썬 코딩 도장] Unit 34. 클래스 사용하기

박뮤트 2022. 1. 3. 12:05

클래스와 메서드 만들기

>>> class Person:
...     def greeting(self):
...         print('Hello')

class에 이름 지정, :(콜론)을 붙인 후 다음 줄에 들여쓰기를 하고 def로 메서드 작성(메서드: 클래스 안에 들어있는 함수)

이름은 보통 대문자로 시작한다. 들여쓰기 규칙은 if, for, while과 같다. 특히 메서드의 첫 번째 매개변수는 self로 지정해야 한다.

메서드 호출하기

>>> james.greeting()
Hello

인스턴스: 클래스에 괄호()를 붙인 뒤 변수에 할당한 것

* 객체이지만, 클래스와 연관지어서 부를 땐 인스턴스라고 한다.

 

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

self.매서드() 형식으로 호출해야 한다. 그렇지 않으면 클래스 바깥에 있는 함수가 호출된다.

class Person:
    def greeting(self):
        print('Hello')
 
    def hello(self):
        self.greeting()    # self.메서드() 형식으로 클래스 안의 메서드를 호출
 
james = Person()
james.hello()    # Hello

특정 클래스의 인스턴스인지 확인하기

특정 클래스의 인스턴스가 맞으면 True, 틀리면 False를 반환한다. 주로 객체의 자료형을 판단할 때 사용한다.

>>> class Person:
...     pass
...
>>> james = Person()
>>> isinstance(james, Person)
True
def factorial(n):
    if not isinstance(n, int) or n < 0:    # n이 정수가 아니거나 음수이면 함수를 끝냄
        return None
    if n == 1:
        return 1
    return n * factorial(n - 1)

속성 사용하기

class 클래스이름:
    def __init__(self):
        self.속성 = 값
class Person:
    def __init__(self):
        self.hello = '안녕하세요.'
 
    def greeting(self):
        print(self.hello)
 
james = Person()
james.greeting()    # 안녕하세요.

인스턴스를 만들 때 값 받기

class Person:
    def __init__(self, name, age, address):
        self.hello = '안녕하세요.'
        self.name = name
        self.age = age
        self.address = address
 
    def greeting(self):
        print('{0} 저는 {1}입니다.'.format(self.hello, self.name))
 
maria = Person('마리아', 20, '서울시 서초구 반포동')
maria.greeting()    # 안녕하세요. 저는 마리아입니다.
 
print('이름:', maria.name)       # 마리아
print('나이:', maria.age)        # 20
print('주소:', maria.address)    # 서울시 서초구 반포동
안녕하세요. 저는 마리아입니다.
이름: 마리아
나이: 20
주소: 서울시 서초구 반포동

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

리스트 언패킹

class Person:
    def __init__(self, *args):
        self.name = args[0]
        self.age = args[1]
        self.address = args[2]
 
maria = Person(*['마리아', 20, '서울시 서초구 반포동'])

딕셔너리 언패킹

class Person:
    def __init__(self, **kwargs):    # 키워드 인수
        self.name = kwargs['name']
        self.age = kwargs['age']
        self.address = kwargs['address']
 
maria1 = Person(name='마리아', age=20, address='서울시 서초구 반포동')
maria2 = Person(**{'name': '마리아', 'age': 20, 'address': '서울시 서초구 반포동'})

추가한 속성은 해당 인스턴스에만 생성된다.

따라서 클래스로 다른 인스턴스를 만들었을 때는 추가한 속성이 생성되지 않는다.

>>> james = Person()    # james 인스턴스 생성
>>> james.name    # maria 인스턴스에만 name 속성을 추가했으므로 james 인스턴스에는 name 속성이 없음
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    james.name
AttributeError: 'Person' object has no attribute 'name'

인스턴스는 생성한 뒤에 속성을 추가할 수 있으므로 __init__매서드가 아닌 다른 메서드에서도 속성을 추가할 수 있다.

단, 이 때 매서드를 호출해야 속성이 생성된다.

>>> class Person:
...     def greeting(self):
...         self.hello = '안녕하세요'    # greeting 메서드에서 hello 속성 추가
...
>>> maria = Person()
>>> maria.hello    # 아직 hello 속성이 없음
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    maria.hello
AttributeError: 'Person' object has no attribute 'hello'

>>> maria.greeting()    # greeting 메서드를 호출해야
>>> maria.hello         # hello 속성이 생성됨
'안녕하세요'

인스턴스에서 특정 속성만 허용하고 다른 속성을 제한하고 싶을 때 클래스에서 __slots__에 허용할 속성 이름을 리스트로 넣어주면 된다. 

특히 속성 이름은 반드시 문자열로 지정한다.

>>> class Person:
...     __slots__ = ['name', 'age']    # name, age만 허용(다른 속성은 생성 제한)
...
>>> maria = Person()
>>> maria.name = '마리아'                     # 허용된 속성
>>> maria.age = 20                            # 허용된 속성
>>> maria.address = '서울시 서초구 반포동'    # 허용되지 않은 속성은 추가할 때 에러가 발생함
Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    maria.address = '서울시 서초구 반포동'
AttributeError: 'Person' object has no attribute 'address'

비공개 속성 사용하기

클래스 바깥에서 접근할 수 있는 속성을 공개 속성, 접근할 수 없는 속성을 비공개 속성이라고 한다.

작성방법: 속성 이름이 __(밑줄 두 개)로 시작한다.단, __속성__처럼 밑줄 두 개가 양 옆에 왔을 때는 비공개 속성이 아니다.

class 클래스이름:
    def __init__(self, 매개변수)
        self.__속성 = 값
class Person:
    def __init__(self, name, age, address, wallet):
        self.name = name
        self.age = age
        self.address = address
        self.__wallet = wallet    # 변수 앞에 __를 붙여서 비공개 속성으로 만듦
 
maria = Person('마리아', 20, '서울시 서초구 반포동', 10000)
maria.__wallet -= 10000    # 클래스 바깥에서 비공개 속성에 접근하면 에러가 발생함
Traceback (most recent call last):
  File "C:\project\class_private_attribute_error.py", line 9, in <module>
    maria.__wallet -= 10000    # 클래스 바깥에서 비공개 속성에 접근하면 에러가 발생함
AttributeError: 'Person' object has no attribute '__wallet' 

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

class Person:
    def __init__(self, name, age, address, wallet):
        self.name = name
        self.age = age
        self.address = address
        self.__wallet = wallet    # 변수 앞에 __를 붙여서 비공개 속성으로 만듦
 
    def pay(self, amount):
        self.__wallet -= amount   # 비공개 속성은 클래스 안의 메서드에서만 접근할 수 있음
        print('이제 {0}원 남았네요.'.format(self.__wallet))
 
maria = Person('마리아', 20, '서울시 서초구 반포동', 10000)
maria.pay(3000)
이제 7000원 남았네요.

비공개 메서드

메서드 이름도 __ 밑줄 두 개로 시작하면 클래스 안에서만 호출할 수 있는 비공개 메서드가 된다.

class Person:
    def __greeting(self):
        print('Hello')
 
    def hello(self):
        self.__greeting()    # 클래스 안에서는 비공개 메서드를 호출할 수 있음
 
james = Person()
james.__greeting()    # 에러: 클래스 바깥에서는 비공개 메서드를 호출할 수 없음