[LG헬로비전 DX DATA SCHOOL 4기] Python(5) (250110)

mini_bang·2025년 1월 10일

파이썬 심화(2)

match-case 구문

  • match-case는 Python 3.10부터 도입된 조건 분기 구문으로, switch-case와 유사.
  • 다양한 값이나 조건을 패턴으로 매칭할 수 있음.
// 실습 코드
match value:

  pattern_1:
    # paatern_1에 일치하는 경우 실행할 코드
  pattern_2:
    # paatern_1에 일치하는 경우 실행할 코드
  ...
  pattern_n:
    # paatern_1에 일치하는 경우 실행할 코드
  _:
    # 위의 패턴이 일치하지 않는 경우 실행할 코드
// 실습 코드
def classify_number(n):
  match n:
    case 0:
      print("Zero")
    case 1 | 2 | 3:
      print("Small number")
    case 4 | 5 | 6 | 7 | 8 | 9:
      print("Big number")
    case _:
      print("Other number")

classify_number(0) # Zero
classify_number(2)  # Small number
classify_number(7)  # Big number
classify_number(10) # Other number

Class

  • 기본 클래스 정의
  • 객체 생성 시 서로 다른 주소를 가진 개별 객체가 생성.
// 실습 코드
class Myclass():
  pass

a = Myclass()
b = Myclass()
c = Myclass()

print(a)
print(b)
print(c)    # 객체의 주소가 각각 다름
  • 은행 계좌 예제
  • make_account, deposit, draw 메서드를 정의해 계좌 기능 구현.
// 실습 코드
class Account():
  def make_account(self):
    self.balance = 0
  def deposit(self, money):
    self.balance += money
  def draw(self, money):
    self.balance -= money

a1 = Account()    # 무조건 인스턴스를 받고 Class를 작동시켜야 함. Account.balance (X)
a1.make_account() # 통장끼리는 잔고를 공유하지 않음.
a1.deposit(1000)
print(a1.balance)

a2 = Account()
a2.make_account()
a2.deposit(5000)
print(a2.balance)
  • 생성자 __init__ 활용
    객체 생성 시 초기 값을 자동으로 설정
    클래스의 함수는 메서드로 불리며, 첫 번째 매개변수는 항상 self로 현재 인스턴스를 참조
// 실습 코드
class person():
  def __init__(self):
    self.age = 17

p1 = person()
p1.age
class person():
  def __init__(self):
    self.age = 17

p1 = person()
p1.age

# AttributeError                            Traceback (most recent call last)
# <ipython-input-16-d7221031635e> in <cell line: 7>()
#       5 p1 = person()
#       6 
# ----> 7 p1.__age

# AttributeError: 'person' object has no attribute '__age'
// 실습 코드
class person():
  def _init__(self):    # _ 짝을 안맞추면 프라이빗하게 바뀜(접근 불가능하게)
    self.age = 17

p1 = person()

p1.age

# AttributeError                            Traceback (most recent call last)
# <ipython-input-17-cfb76646878b> in <cell line: 7>()
#       5 p1 = person()
#       6 
# ----> 7 p1.age

# AttributeError: 'person' object has no attribute 'age'
// 실습 코드
class TestClass1():
  def __init__(self, in1, in2):   # 인스턴스 메소드의 매개변수 중 가장 첫번째는 인스턴스의 자리
    self.v1 = in1
    self.v2 = in2

t_cls1 = TestClass1(10, 20)
t_cls1.v1
// 실습 코드
class TestClass1():
  def __init__(in1, in2):   # 매개변수에 인스턴스도 포함 해줘야함 !!
    self.v1 = in1
    self.v2 = in2

t_cls1 = TestClass1(10, 20)
t_cls1.v1

# TypeError                                 Traceback (most recent call last)
# <ipython-input-20-cd5fe822b043> in <cell line: 6>()
#       4     self.v2 = in2
#       5 
# ----> 6 t_cls1 = TestClass1(10, 20)
#       7 t_cls1.v1

# TypeError: TestClass1.__init__() takes 2 positional arguments but 3 were given
  • __init__: 객체 생성 시 초기화
  • __del__: 객체 소멸 시 호출
// 실습 코드
class test():
  name = '아무나'
  age = 0
  def __init__(self, name, age):
    print('생성자 호출!')
    self.name = name
    self.age = age
  def __del__(self):
    print('소멸자 호출!')
  def info(self):
    print('나의 이름은', self.name, '입니다!')
    print('나이는', self.age, '입니다!')

r = test('minibang', 7)
r.info()    # test.info() --> X
// 실습 코드
class ClassExample:
  def __init__(self, name, age):  # 생성자(Constructor) 생성 시 자동 수행
    self.name = name
    self.age = age + 5  # 변수 생성 후 파라미터로 보낸 값 할당
    print("[생성자] self와 변수 비교 " + str(self.age) + " age : " + str(age))
    print("[생성자] 이름 : " + self.name + " 나이 : " + str(self.age))

  def ten_year_call(self, val): # 함수
    return self.age + 10  # 반환

a = ClassExample("철수", 20) # 객체화(ClassExaple의 정보를 a에 담음)
print(a.age) # a의 age출력
print(a.ten_year_call(50))  # a의 ten_year_call 메소드 수행

# 객체화 : 해당 클래스의 정보를 변수 안에 넣어서 변수를 가지고 해당 클래스에
# 사용할 수 있다는 이야기를 할 수 있음.
// 실습 코드
class CustomNumbers:
  def __init__(self):
    self._numbers = [n for n in range(1, 11)]
a = CustomNumbers()

a[2:5]    # 객체의 슬라이싱이 불가능함. => __getitem__ 특별 메서드를 정의해야 함.

# TypeError                                 Traceback (most recent call last)
# <ipython-input-32-192e4989a914> in <cell line: 6>()
#       4 a = CustomNumbers()
#       5 
# ----> 6 a[2:5]    # 객체의 슬라이싱이 불가능함.

# TypeError: 'CustomNumbers' object is not subscriptable
// 실습 코드
a._numbers[2:5] # 인스턴스 변수에 직접 접근하여 슬라이싱 하는 방법
  • 객체에서 슬라이싱 가능하도록 구현(__getitem__)
// 실습 코드
# 인스턴스 변수에 직접 접근하지 말고 객체 자체를 통해서 슬라이싱을 구현하기 위해서는
# __getiterm__ 특별 메서드를 정의해야 함.
class CustomNumbers:
  def __init__(self):
    self._numbers = [n for n in range(1, 11)]
  def __getitem__(self, idx):
    return self._numbers[idx]

a = CustomNumbers()
a[2:7]
  • 클래스 메서드 (@classmethod)
    클래스 메서드는 클래스 변수에 접근하거나 클래스 수준의 작업을 수행
    첫 번째 매개변수로 cls를 받음.
// 실습 코드
class MyClass2():
  class_var = '클래스 변수'

  @classmethod    # 인스턴스 메소드에 @classmethod 데코레이터(decorator)를 사용하면 클래스 메소드가 된다. 따라서 클래스의 속성에 접근할 수 있게 된다.
  def class_method(cls): # cls : 인스턴스
    print('클래스의 메소드')

e = MyClass2()
print(e.class_var)
print(MyClass2.class_var)

e. class_method()
MyClass2.class_method()   # 원래 안되는데 @classmethod를 써서 작동이 되는 것임
  • 정적 메서드 (@staticmethod)
  • 클래스나 인스턴스와 관계없이 독립적으로 작동하는 메서드
  • 첫 번째 매개변수로 self나 cls를 받지 않음
// 실습 코드
# 실제로는 @staticmethod를 더 많이 사용함
class Calc:
  @staticmethod
  def add(a, b):
    print(a + b)

  @staticmethod
  def mul(a, b):
    print(a * b)

Calc.add(10, 20)    # 클래스에서 바로 메서드 호출
Calc.mul(10, 20)    # 클래스에서 바로 메서드 호출
  • 클래스 변수와 인스턴스 변수
    클래스 변수: 클래스 전체에서 공유되는 변수.
    인스턴스 변수: 각 인스턴스마다 고유한 값을 가짐.

  • 클래스 변수와 클래스 메서드 활용 예제

// 실습 코드
# 변수를 먼저 할당 -> 그다음 연산을 정의
# 연산을 먼저 정의 (@classmethod를 이용함) -> 그다음 변수를 할당

class Account2():
  bank = '모두은행' # 클래스 변수
  total = 0 # 클래스 변수

  @classmethod
  def merge(cls, acc1, acc2):
    cls.total = acc1.balance + acc2.balance
    print("당신의 재산은 %d" %cls.total)

  def __init__(self):
    self.balance = 0

  def deposit(self, money):
    self.balance += money

  def draw(self, money):
    self.balance -= money

Account2.bank

b1 = Account2()
b1.deposit(4000)
print(b1.balance)
print(b1.bank)

b2 = Account2()
b2.deposit(7000)
print(b2.balance)
print(b2.bank)

Account2.merge(b1, b2)
Account2.total
  • 객체와 클래스 간의 데이터 공유
    인스턴스 변수는 클래스 수준에서 직접 접근 불가
// 실습 코드
class Hotel():
  def __init__(self):
    self.room = []
  def add_person(self, name):
    self.room.append(name)

r1 = Hotel()  # 각각 인스턴스를 받음.
r2 = Hotel()  # 각각 인스턴스를 받음.

r1.add_person('뽀로로')
r2.add_person('펭수')

Hotel.room    # person이 추가가 되었는데 방안에 왜 접근이 안되는가?
# => class이기 때문에 밖으로 호출이 안됨.

# AttributeError                            Traceback (most recent call last)
# <ipython-input-49-028058acf03e> in <cell line: 1>()
# ----> 1 Hotel.room    # 실행이 안됨. 데코레이터를 안써서 클래스 객체 자체 접근 불가?

# AttributeError: type object 'Hotel' has no attribute 'room'
  • 클래스 변수와 클래스 메서드를 활용하여 해결
// 실습 코드
class GuestHouse():
  guest = []

  def __init__(self):
    self.room = []

  @classmethod
  def check_in(cls, name):
    cls.guest.append(name)

  def add_person(self, name):
    self.check_in(name)
    self.room.append(name)

r3 = GuestHouse()
r4 = GuestHouse()

r3.check_in('뚝딱이')
r4.check_in('뿡뿡이')

GuestHouse.guest	# ['뚝딱이', '뿡뿡이']
// 실습 코드
r3.room		# []
r4.room		# []
r3.add_person('홍길동')
r4.add_person('텔레토비')
r3.room		# ['홍길동']
r4.room		# ['텔레토비']
GuestHouse.guest	# ['뚝딱이', '뿡뿡이', '홍길동', '텔레토비']
  • 클래스 상속
    부모 클래스의 메서드와 속성을 자식 클래스에서 사용 가능
// 실습 코드
# 클래스 상속
class MyPhone():
  def __init__(self, model, color):
    self.model = model
    self.color = color
  def set_name(self, name):
    self.user = name
    print('사용자의 이름은 : %s' %self.user)
  def set_number(self, number):
    self.number = number

class MyPhone2(MyPhone):    # 부모클래스(MyPhone)으로 부터 클래스를 상속받음
  def has_case(self, val = False): # 자식클래스(MyPhone2)의 새로운 메소드
    self.case = val

p2 = MyPhone2('iphone', 'red')
p2.set_name("MJ")	# 사용자의 이름은 : MJ
// 실습 코드
p2.has_case(True)
p2.case		# True
// 실습 코드
# 클래스 상속
class MyPhone():
  def __init__(self, model, color):
    self.model = model
    self.color = color
  def set_name(self, name):
    self.user = name
    print('사용자의 이름은 : %s' %self.user)
  def set_number(self, number):
    self.number = number

p1 = MyPhone('iphone', 'red')
p1.set_number("010-xxxx-xxxx")
  • 메서드 오버라이딩
    부모 클래스의 메서드를 자식 클래스에서 재정의
// 실습 코드
# 메서드 오버라이딩(method overriding)은 부모 클래스로부터 상속받은 특정 메서드를
# 자식 클래스에서 재정의하는 작업을 의미
class MyPhone3(MyPhone):
  def set_number(self, num):
    self.number = num
    print("이 핸드폰의 번호는 : %s" %self.number)

p3 = MyPhone3('iphone', 'red')
p3.set_number("010-xxxx-xxxx")	# 이 핸드폰의 번호는 : 010-xxxx-xxxx

연습문제

  • Human 클래스 정의
// 실습 코드
# 연습문제 (1)
# Human이라는 클래스를 만들어보자.
# Human클래스는 아래와 같은 특징이 있다.
# Human클래스는 인스턴스 생성 시 birth_date, sex, nation을 변수로 가지고 있다.
# give_name은 인스턴스 메소드로 이름을 input으로 받아서 name이라는 인스턴스 변수로 저장하고 화면에 이름을 출력하는 역할을 하는 함수이다.
# can_sing이라는 함수는 True/False값을 input으로 받으며, 참이면 "Sing a song"을 화면에 출력하는 함수이다.
class Human():
  def __init__(self, birth_date, sex, nation):
    self.birth_date = birth_date
    self.sex = sex
    self.nation = nation
  def give_name(self, name):
    self.name = name
    print("이름 : %s" %self.name)
  def can_sing(self, ability):
    if ability:
      print("Sing a song")

a = Human(990316, 'M', 'Korea')

a.give_name('minibang')		# 이름 : JBM
a.can_sing(True)		# Sing a song
  • Child 클래스 상속
// 실습 코드
# 연습문제 (2)
# Human이라는 클래스를 상속하는 Child라는 클래스를 만들어보자.
# Child의 클래스에는 아래와 같은 변수와 함수들이 추가된다.
# 눈동자 색깔을 나타내는 변수 eye를 인스턴스 선언시 사용할 수 있게 추가해보자.
# Child의 클래스는 노래하는 능력이 없다. 따라서 can_sing이라는 메소드가 호출되면 무조건 "Can't Sing"이라고 출력하도록 바꿔보자.
# Child는 노래 대신 춤을 출 수 있다. can_dance라는 메소드가 호출되면 "Dance Time!"을 출력하도록 메소드를 작성해보자.

class Child(Human):
  def __init__(self, birth_date, sex, nation, eye):
    self.birth_date = birth_date
    self.sex = sex
    self.nation = nation
    self.eye = eye

  def can_sing(self):
    print("Can't Sing")

  def can_dance(self):
    print("Dance Time!")

b = Child(990316, "M", "Korea", "black")

b.nation
b.can_sing()	# Can't Sing
b.can_dance()	# Dance Time!
  • super를 활용한 Child 클래스
// 실습 코드
# super를 사용하여 구현
class ChildSuper(Human):
  def __init__(self, birth_date, sex, nation, eye):
    super().__init(birth_date, sex, nation)     # super를 쓰면 다른 클래스에서 가져올 수 있음.

  def can_sing(self):
    print("Can't Sing")

  def can_dance(self):
    print("Dance Time!")

c = Child(990316, "M", "Korea", "black")

c.nation
c.can_sing()	# Can't Sing
c.can_dance()	# Dance Time!

0개의 댓글