관리 메뉴

Doby's Lab

상속을 ν•  λ•Œ, super().__init__()을 ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄? λ³Έλ¬Έ

Code about AI/Python

상속을 ν•  λ•Œ, super().__init__()을 ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄?

도비(Doby) 2023. 11. 11. 00:03

πŸ€” Intro

PyTorchλ₯Ό κ³΅λΆ€ν•˜λ‹€κ°€ νŒŒμ΄μ¬μ—μ„œ OOPλ₯Ό ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

μ˜ˆμ „μ— νŒŒμ΄μ¬μ—μ„œ Class에 λŒ€ν•΄ κ³΅λΆ€ν•œ 것과 이번 학기에 ν•™κ΅μ—μ„œ κ³΅λΆ€ν•˜κ²Œ 된 객체지ν–₯ν”„λ‘œκ·Έλž˜λ°(Java)을 톡해 상속(inheritance)에 λŒ€ν•œ κ°œλ…μ„ μ•Œκ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

더 λ‚˜μ•„κ°€ PyTorch 핸듀링을 μœ„ν•΄ 파이썬의 상속에 λŒ€ν•΄ μΆ”κ°€μ μœΌλ‘œ μ•Œκ²Œ 된 점듀을 μ •λ¦¬ν•΄λ³΄κ³ μž ν•©λ‹ˆλ‹€.

(+ κ°œλ… 정리 μ•„λ‹™λ‹ˆλ‹€. κ°œλ…μ— λŒ€ν•΄μ„œλŠ” 정리가 잘 된 뢀뢄듀이 λ§ŽκΈ°μ— κΆκΈˆν•œ λΆ€λΆ„λ“€λ§Œ μ •λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.)

 

ν•΄λ‹Ή ν¬μŠ€νŒ…μ—μ„œλŠ” λΆ€λͺ¨ 클래슀λ₯Ό μƒμ†λ°›λŠ” μžμ‹ 클래슀의 Constructor(__init__ λ©”μ„œλ“œ)μ—μ„œ super().__init__()의 μœ λ¬΄μ— λ”°λ₯Έ 차이λ₯Ό μ•Œμ•„λ΄…λ‹ˆλ‹€.


πŸ€” μžμ‹ ν΄λž˜μŠ€μ—μ„œ super().__init__()을 ν•˜μ§€ μ•ŠμœΌλ©΄?

μ•„λž˜μ™€ 같이 Person ν΄λž˜μŠ€μ™€ 그에 λŒ€ν•œ μžμ‹ 클래슀인 Studentκ°€ μžˆλ‹€κ³  ν•©μ‹œλ‹€.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def print_name(self):
        print(f'this object\'s name is {self.name}')
        
    def print_age(self):
        print(f'this object\'s age is {self.age}')
        
    def print_hello(self):
        print('Say HELLO!')
        
class Student(Person):
    def __init__(self, name, age, grade):
        # super().__init__(name, age)
        self.grade = grade
        
    def print_grade(self):
        print(f'this object\'s grade is {self.grade}')

 

μ—¬κΈ°μ„œ s1μ΄λΌλŠ” Student의 였브젝트λ₯Ό μ„ μ–Έν•˜μ—¬ print_age()λ₯Ό ν˜ΈμΆœν•΄ λ΄…μ‹œλ‹€.

s1 = Student('James', 12, 3)
s1.print_age()

 

κ²°κ³ΌλŠ” μ•„λž˜μ™€ 같은 였λ₯˜λ₯Ό 좜λ ₯ν•©λ‹ˆλ‹€.

Cell In[33], line 10, in Person.print_age(self)
      9 def print_age(self):
---> 10     print(f'this object\'s age is {self.age}')

AttributeError: 'Student' object has no attribute 'age'

 

Q: λΆ„λͺ… Personμ—μ„œ 상속을 λ°›μ•˜λŠ”λ° μ™œ ageλ₯Ό κ°–κ³  μžˆμ§€ μ•Šμ£ ?

 

νŒŒμ΄μ¬μ—μ„œλŠ” Class에 λŒ€ν•΄μ„œ __init__()을 가지고 μžˆλŠ”λ° μ—¬κΈ° Constructorμ—μ„œ μ „λ°˜μ μœΌλ‘œ ν•΄λ‹Ή Class에 λŒ€ν•œ ν•„λ“œλ₯Ό λͺ¨λ‘ κ΄€λ¦¬ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. (Java와 달리 ν•„λ“œλ₯Ό μžλ™μœΌλ‘œ λ„˜κ²¨μ£Όμ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€. λ¬Όλ‘ , 그것도 μ ‘κ·Ό μ§€μ •μžμ— 따라 λ‹€λ¦…λ‹ˆλ‹€.) κ·Έλž˜μ„œ μžμ‹ 클래슀의 __init__()μ—μ„œ λΆ€λͺ¨ 클래슀의 ν•„λ“œλ₯Ό κ°€μ Έμ˜¬ 수 μžˆλ„λ‘ super().__init__()을 ν˜ΈμΆœν•΄μ£Όμ–΄μ•Ό ν•©λ‹ˆλ‹€.

 

즉, μ„±κ³΅μ μœΌλ‘œ print_age()λ₯Ό μ‹€ν–‰μ‹œμΌœ μ£ΌκΈ° μœ„ν•΄μ„œλŠ” μœ„ class μž‘μ„± μ½”λ“œμ—μ„œ 주석 뢀뢄을 ν’€μ–΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

 

Q: λ§Œμ•½μ— Classμ—μ„œ Constructor(__init__())을 μ•„μ˜ˆ λ§Œλ“€μ§€ μ•ŠλŠ”λ‹€λ©΄μš”?

 

κ·ΈλŸ¬ν•œ κ²½μš°μ—λŠ” νŒŒμ΄μ¬μ€ λΆ€λͺ¨ 클래슀의 Constructorλ₯Ό μžλ™μœΌλ‘œ ν˜ΈμΆœν•©λ‹ˆλ‹€. λΆ€λͺ¨ ν΄λž˜μŠ€κ°€ μ—†λŠ” 클래슀라면, 파이썬의 'object'λΌλŠ” 클래슀λ₯Ό λΆ€λͺ¨ 클래슀둜 두고 μƒμ„±λ©λ‹ˆλ‹€. μ•„λž˜ μ½”λ“œκ°€ 이에 λŒ€ν•œ 닡변이 될 수 μžˆμŠ΅λ‹ˆλ‹€.

# Sub Classμ—μ„œ Constructorλ₯Ό callν•˜μ§€ μ•ŠλŠ”λ‹€.
# λͺ…μ‹œμ μœΌλ‘œ 해두지 μ•ŠλŠ” 경우, μžλ™μœΌλ‘œ λΆ€λͺ¨ 클래슀의 μƒμ„±μžκ°€ ν˜ΈμΆœλœλ‹€.

class Stock:
    def __init__(self, name, shares, price):
        self.name = name
        self.shares = shares
        self.price = price
    
    def cost(self):
        return self.shares * self.shares
    
    def sell(self, nshares):
        self.shares -= nshares
        
class MyStock(Stock):
    def panic(self):
        self.sell(self.shares)
        
# μžλ™μœΌλ‘œ λΆ€λͺ¨ 클래슀의 Constructorκ°€ 호좜되기 λ•Œλ¬Έμ— λΆ€λͺ¨ 클래슀의
# Constructorλ₯Ό λ”°λΌμ„œ Objectλ₯Ό μƒμ„±ν•œλ‹€.

s = MyStock('GOOG', 100, 490.1)

s.sell(25)
print(s.shares)

 

75λ₯Ό 좜λ ₯ν•©λ‹ˆλ‹€.


πŸ€” λ©”μ„œλ“œλŠ” 그럼 μžλ™μœΌλ‘œ μƒμ†λ˜λŠ”κ°€?

λ„€, λ§žμŠ΅λ‹ˆλ‹€. ν•„λ“œλŠ” __init__()으둜 μ—„κ²©ν•˜κ²Œ κ΄€λ¦¬λ˜λŠ” 데에 λ°˜ν•΄ λ©”μ„œλ“œλŠ” μžλ™μœΌλ‘œ μƒμ†λ©λ‹ˆλ‹€.

μ•„κΉŒ μœ„ Personκ³Ό Student ν΄λž˜μŠ€μ— λŒ€ν•΄ μž‘μ„±λœ μ½”λ“œμ—μ„œ 주석이 κ·ΈλŒ€λ‘œ 된 μƒνƒœλ₯Ό 생각해 λ΄…μ‹œλ‹€.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def print_name(self):
        print(f'this object\'s name is {self.name}')
        
    def print_age(self):
        print(f'this object\'s age is {self.age}')
        
    def print_hello(self):
        print('Say HELLO!')
        
class Student(Person):
    def __init__(self, name, age, grade):
        # super().__init__(name, age)
        self.grade = grade
        
    def print_grade(self):
        print(f'this object\'s grade is {self.grade}')

 

μ—¬κΈ°μ„œ λ‹€μ‹œ s1μ΄λΌλŠ” 였브젝트λ₯Ό μ„ μ–Έν•˜μ—¬ print_hello()λ₯Ό ν˜ΈμΆœν•΄ λ΄…μ‹œλ‹€.

s1 = Student('James', 12, 3)
s1.print_hello()

 

Say HELLO!

  

print_hello()λŠ” ν•„λ“œμ™€ μ—°κ΄€ μ—†λŠ” λ©”μ„œλ“œλΌμ„œ 잘 좜λ ₯이 λ©λ‹ˆλ‹€. 즉, λ©”μ„œλ“œλŠ” 상속이 μžλ™μœΌλ‘œ 잘 λœλ‹€λŠ” μ–˜κΈ°μž…λ‹ˆλ‹€.


πŸ˜€ Summary

  1. ν•„λ“œλŠ” 였직 Constructorλ₯Ό 톡해 μ—„κ²©ν•˜κ²Œ 상속에 λŒ€ν•œ κ΄€λ¦¬λ˜λ©°, μ‚¬μš©μžμ— μ˜ν•΄ λΆ€λͺ¨ 클래슀의 ν•„λ“œ(super().__init__())λ₯Ό κ°€μ Έμ˜€κ±°λ‚˜ μƒˆλ‘œμš΄ ν•„λ“œλ₯Ό μ»¨νŠΈλ‘€ν•  수 μžˆλ„λ‘ ν•©μ‹œλ‹€.
  2. 그리고, Constructorκ°€ μ—†λŠ” κ²½μš°μ—λŠ” μžλ™μœΌλ‘œ λΆ€λͺ¨ 클래슀의 Constructorλ₯Ό μ‹€ν–‰ν•˜μ—¬ λΆ€λͺ¨ 클래슀의 ν•„λ“œλ₯Ό 가지도둝 ν•©λ‹ˆλ‹€.
  3. λ©”μ„œλ“œλŠ” μ•Œμ•„μ„œ μžλ™μœΌλ‘œ 상속이 λ©λ‹ˆλ‹€. -> λ©”μ„œλ“œ μ˜€λ²„λ‘œλ”©, μ˜€λ²„λΌμ΄λ”© κ΄€λ ¨ν•΄μ„œλŠ” λ‹€μŒμ— λ‹€λ£° μ΄μœ κ°€ 생긴닀면 λ‹€λ£¨μ–΄λ³΄κ² μŠ΅λ‹ˆλ‹€.
  4. λ˜ν•œ, super().__init__()κ³Ό super().__init__(class_name, self)의 차이점에 λŒ€ν•΄μ„œλ„ λ‹€μŒμ— λ‹€λ£¨μ–΄λ³΄κ² μŠ΅λ‹ˆλ‹€.
728x90