ν‹°μŠ€ν† λ¦¬ λ·°

728x90

<λͺ©μ°¨>

    πŸ“ κ°μ²΄ 지ν–₯ ν”„λ‘œκ·Έλž˜λ°(Object Oriented Programming, OOP)

     

    πŸ“ 객체(Object)

    βœ”οΈ μˆ«μžμ—μ„œ ν•¨μˆ˜κΉŒμ§€ 파이썬의 λͺ¨λ“  것은 객체닀. 

    num = 7을 μž…λ ₯ν–ˆμ„ λ•Œ 7이 λ‹΄κΈ΄ μ •μˆ˜ μœ ν˜•μ˜ 객체λ₯Ό μƒμ„±ν•˜κ³  객체 μ°Έμ‘°(object reference)λ₯Ό num에 ν• λ‹Ήν•œλ‹€. 

     

    βœ”οΈ κ°μ²΄λŠ” 데이터(λ³€μˆ˜, 속성)와 μ½”λ“œ(ν•¨μˆ˜, λ©”μ„œλ“œ)λ₯Ό ν¬ν•¨ν•˜λŠ” μ»€μŠ€ν…€ μžλ£Œκ΅¬μ‘°μ΄λ‹€. 

    ν•¨μˆ˜ : 객체 μ™Έμ˜ μ½”λ“œ λ­‰μΉ˜
    λ©”μ„œλ“œ :  클래슀 μ•ˆμ˜ 멀버 μ™Έμ˜ μ½”λ“œ λ­‰μΉ˜

     

    βœ”οΈ κ°μ²΄λŠ” ꡬ체적인 μ–΄λ–€ κ²ƒμ˜ μœ μΌν•œ μΈμŠ€ν„΄μŠ€(instance)λ₯Ό 가리킨닀.

    βœ”οΈ κ°μ²΄λŠ” μ •μ˜λœ 클래슀λ₯Ό 톡해 μƒμ„±λœλ‹€. 객체 != 클래슀

     

    πŸ“ ν΄λž˜μŠ€(Class)

    βœ”οΈ κ°μ²΄μ˜ 틀을 λ‚˜νƒ€λ‚Έλ‹€. 

    class Cat:
        pass

     

    βœ”οΈ Cat()은 Cat ν΄λž˜μŠ€λ‘œλΆ€ν„° κ°œλ³„ 객체λ₯Ό μƒμ„±ν•˜μ—¬ 객체 μ°Έμ‘°λ₯Ό a_catκ³Ό another_cat에 ν• λ‹Ήν•œλ‹€. 

    - a_catκ³Ό another_cat은 같은 클래슀의 λ‹€λ₯Έ κ°μ²΄μ΄λ―€λ‘œ λ‹€λ₯΄κ²Œ λ§΅ν•‘λœλ‹€. 

    a_cat = Cat()
    another_cat = Cat()
    
    print(a_cat)
    <__main__.Cat object at 0x000002050461D9A0>
    
    print(another_cat)
    <__main__.Cat object at 0x000002050461DD30>

     

    πŸ“ 속성(Attribute)

    βœ”οΈ μ†μ„±μ€ ν΄λž˜μŠ€λ‚˜ 객체 λ‚΄λΆ€μ˜ λ³€μˆ˜λ‹€.

    βœ”οΈ κ°μ²΄λ‚˜ ν΄λž˜μŠ€κ°€ μƒμ„±λ˜λŠ” λ™μ•ˆμ—λ„ 생성 κ°€λŠ₯ν•˜μ§€λ§Œ 생성 이후에도 속성을 μΆ”κ°€ μž‘μ„±ν•  수 μžˆλ‹€. 

    # Cat ν΄λž˜μŠ€μ— μ„ μ–Έλ˜μ–΄ μžˆμ§€ μ•Šμ€ 속성을 μΆ”κ°€λ‘œ μ‚¬μš© κ°€λŠ₯
    a_cat.age = 3
    a_cat.name = "cat"
    a_cat.nemesis = another_cat
    
    a_cat.age
    Out[102]: 3
    
    a_cat.name
    Out[100]: 'cat'
    
    a_cat.nemesis
    Out[101]: <__main__.Cat at 0x2050461dd30>

     

    πŸ“ λ©”μ„œλ“œ(Method)

    βœ”οΈ λ©”μ„œλ“œλŠ” 클래슀 λ˜λŠ” 객체의 ν•¨μˆ˜λ‹€. 

    βœ”οΈ __init__() : κ°œλ³„ 객체λ₯Ό μ΄ˆκΈ°ν™”ν•˜λŠ” 특수 λ©”μ„œλ“œ

    __init__() λ©”μ„œλ“œλŠ” λ‹€λ₯Έ μ–Έμ–΄μ—μ„œμ˜ "μƒμ„±μž"의 κ°œλ…μ΄ μ•„λ‹ˆλ‹€.
    __init__() λ©”μ„œλ“œ 호좜 전에 이미 객체가 λ§Œλ“€μ–΄μ Έ 있기 λ•Œλ¬Έμ΄λ‹€. 

    βœ”οΈ self : κ°œλ³„ 객체 μžμ‹ μ„ μ°Έμ‘°

    class Cat():
        def __init__(self, name):
            self.name = name
    self.name의 경우 λͺ…μ‹œμ μœΌλ‘œ 클래슀의 μ†μ„±μœΌλ‘œ μ„ μ–Έλ˜μ–΄ μžˆμ§€λŠ” μ•Šμ§€λ§Œ 클래슀 내에 μ†μ„±μœΌλ‘œμ¨ μ‚¬μš© κ°€λŠ₯ν•˜λ‹€. 

     

    πŸ“ κ°μ²΄ 상속

    πŸ“„ 상속(inherit)

    객체의 μ£Όμš” νŠΉμ„± : μΊ‘μŠν™”, 상속, 좔상화, λ‹€ν˜•μ„±

    βœ”οΈ ν•„μš”ν•œ κΈ°λŠ₯은 기쑴의 것을 μ‚¬μš©ν•˜μž!! μž¬μ‚¬μš©!!

     

    - λΆ€λͺ¨ 클래슀 : 기쑴의 것

    - μžμ‹ 클래슀 : νŒŒμƒλœ 것, sub class

    class Car:
    	pass
    class Yugo(Car):
    	pass

     

    βœ”οΈ issubclass(a, b) : aκ°€ b의 μ„œλΈŒ 클래슀 인가?

    issubclass(Yugo, Car)
    Out[15]: True

     

    πŸ’‘ data type의 상속

    bool은 int의 μ„œλΈŒ ν΄λž˜μŠ€μ΄λ‹€. = bool은 intλ₯Ό μƒμ†λ°›λŠ”λ‹€. 

    issubclass(bool, int)
    Out[21]: True
    
    issubclass(int, bool)
    Out[23]: False
    
    issubclass(int, float)
    Out[22]: False
    
    issubclass(float, int)
    Out[25]: False

     

    isinstance()

     

    πŸ“„ μžμ‹ 클래슀

    βœ”οΈ λΆ€λͺ¨ 클래슀의 νŠΉμ§•μ„ κ°€μ Έμ˜¬ 수 μžˆλ‹€. (= 상속 λ°›λŠ”λ‹€.)

    νŠΉμ§• : λ©”μ„œλ“œ, 멀버, λ™μž‘ κ³Όμ • λ“±
    class Car():
    	def exclaim(self):
    		print("I am a Car!")
    class Yugo(Car):
    	pass
    give_me_a_car = Car()
    give_me_a_yugo = Yugo()
    
    give_me_a_car.exclaim()
    I am a Car!
    
    give_me_a_yugo.exclaim()
    I am a Car!

     

    βœ”οΈ μžμ‹ 클래슀만의 μƒˆλ‘œμš΄ κΈ°λŠ₯을 μ •μ˜ν•  수 μžˆλ‹€. 

    λ©”μ„œλ“œ λͺ…이 μƒˆλ‘­λ‹€λ©΄ μƒˆλ‘­κ²Œ μ •μ˜λ˜κ³ , λ©”μ„œλ“œ λͺ…이 κ°™λ‹€λ©΄ μž¬μ •μ˜(override) λœλ‹€. 

     

    πŸ“„ μ˜€λ²„λΌμ΄λ“œ(override, μž¬μ •μ˜)

    override vs overload
    class Car():
    	def exclaim(self):
    		print("I am a Car!")
    class Yugo(Car):
    	def exclaim(self):
    		print("I am a Yugo!")
    give_me_a_car = Car()
    give_me_a_yugo = Yugo()
    
    give_me_a_car.exclaim()
    I am a Car!
    
    give_me_a_yugo.exclaim()
    I am a Yugo!

     

    βœ”οΈ __init__() λ©”μ„œλ“œλ„ μ˜€λ²„λΌμ΄λ“œ λœλ‹€. 

    class Person:
        def __init__(self, name):
            self.name = name
            
    class MDPerson(Person):
        def __init__(self, name):
            self.name = "Doctor " + name
            
    class JDPerson(Person):
        def __init__(self, name):
            self.name = name + ", Esquire"
    person = Person("Riri")
    doctor = MDPerson("Riri")
    lawyer = JDPerson("Riri")
    
    person.name
    Out[53]: 'Riri'
    
    doctor.name
    Out[52]: 'Doctor Riri'
    
    lawyer.name
    Out[54]: 'Riri, Esquire'

     

    πŸ“„ Super()

    βœ”οΈ 상속받은 객체가 λΆ€λͺ¨ 객체λ₯Ό μš”μ²­ν•  λ•Œ μ‚¬μš©ν•œλ‹€.

    βœ”οΈ λΆ€λͺ¨ 클래슀의 μ •μ˜λ₯Ό μ–»μ–΄μ˜¨λ‹€. 

     

    βœ”οΈ super().__init__(name)

    λΆ€λͺ¨ 클래슀의 name을 인수둜 λ°›μ•„μ˜¨ name으둜 μ΄ˆκΈ°ν™” ν•΄μ€€λ‹€. 

    μžμ‹ ν΄λž˜μŠ€μ—μ„œ __init__() λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œ ν•΄μ„œ μ‚¬μš©ν–ˆκΈ° λ•Œλ¬Έμ— 이λ₯Ό 쓰지 μ•ŠμœΌλ©΄ λΆ€λͺ¨ 클래슀의 __init__() ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μ‚¬μš©ν•΄μ•Όν•œλ‹€. 

    class Person:
        def __init__(self, name):
            self.name = name
            
    class EmailPerson(Person):
        def __init__(self, name, email):
            super().__init__(name)
            self.email = email
    bob = EmailPerson("Bob Frapples", "bob@frapples.com")
    
    bob.name
    Out[31]: 'Bob Frapples'
    
    bob.email
    Out[32]: 'bob@frapples.com'

     

    πŸ“„ 닀쀑 상속

    βœ”οΈ κ°μ²΄λŠ” μ—¬λŸ¬ λΆ€λͺ¨ 클래슀λ₯Ό 상속받을 수 μžˆλ‹€. 

    class Animal:
    	def says(self):
    		return "I speak"
            
    class Horse(Animal):
    	def says(self):
    		return "Neigh"
        
    class Donkey(Animal):
    	def says(self):
    		return "Hee-haw"
        
    class Mule(Donkey, Horse):
    	pass
        
    class Hinny(Horse, Donkey):
    	pass

     

    πŸ’‘ λ©”μ„œλ“œ 해석 μˆœμ„œ - mro()

    λ‹€μŒκ³Ό 같은 μˆœμ„œλ‘œ ν΄λž˜μŠ€μ—μ„œ λ©”μ„œλ“œλ‚˜ 속성을 μ°ΎλŠ”λ‹€. 

    객체 μžμ‹  → 객체의 클래슀 → 첫번째 λΆ€λͺ¨ 클래슀 → λ‘λ²ˆμ§Έ λΆ€λͺ¨ 클래슀 → λΆ€λͺ¨ 클래슀
    Mule.mro()
    Out[34]: [__main__.Mule, __main__.Donkey, __main__.Horse, __main__.Animal, object]
    
    Hinny.mro()
    Out[35]: [__main__.Hinny, __main__.Horse, __main__.Donkey, __main__.Animal, object]
    mule = Mule()
    hinny = Hinny()
    
    mule.says()
    Out[43]: 'Hee-haw'
    
    hinny.says()
    Out[44]: 'Neigh'

     

    πŸ“„ λ―ΉμŠ€μΈ / μ»΄ν¬μ§€μ…˜

     

    πŸ“ 객체 속성 μ ‘κ·Ό - μΊ‘μŠν™” 

    Python vs Java

    πŸ“„ μ§μ ‘ μ ‘κ·Ό

    βœ”οΈ νŒŒμ΄μ¬μ€ 일반적으둜 객체 속성과 λ©”μ„œλ“œκ°€ κ³΅κ°œλ˜μ–΄ μžˆμ–΄ 직접 접근이 κ°€λŠ₯ν•˜λ‹€. 

    βœ”οΈ ν•˜μ§€λ§Œ λ‹€μŒκ³Ό 같이 클래슀 μ™ΈλΆ€μ—μ„œ λ³Ό 수 없도둝 μ…‹νŒ…ν•œ 속성(private attribute)μ—λŠ” μ ‘κ·Όν•˜μ§€ λͺ»ν•œλ‹€. 

    class Blink():
        def __init__(self, input_name, input_pw):
            self.name = input_name
            self.__password = input_pw
    blink = Blink("Riri", "ilovelisa")
    
    blink.name
    Out[84]: 'Riri'
    
    blink.__password
    Traceback (most recent call last):
      File "C:\Anaconda\lib\site-packages\IPython\core\interactiveshell.py", line 3437, in run_code
        exec(code_obj, self.user_global_ns, self.user_ns)
      File "<ipython-input-85-94be706f037f>", line 1, in <module>
        blink.__password
    AttributeError: 'Blink' object has no attribute '__password'
    
    blink.password
    Traceback (most recent call last):
      File "C:\Anaconda\lib\site-packages\IPython\core\interactiveshell.py", line 3437, in run_code
        exec(code_obj, self.user_global_ns, self.user_ns)
      File "<ipython-input-86-122aad938aa4>", line 1, in <module>
        blink.password
    AttributeError: 'Blink' object has no attribute 'password'

     

    πŸ’‘ λ„€μž„ 맹글링(name mangling)

    클래슀 μ •μ˜λ₯Ό μ™ΈλΆ€μ—μ„œ λ³Ό 수 없도둝 ν•˜λŠ” 속성에 λŒ€ν•œ 넀이밍 μ»¨λ²€μ…˜(naming convention)이닀. 

     

    - 속성 이름 μ•žμ— 두 언더바(__)둜 적용

    - μ†μ„±μ˜ μ˜λ„μ μΈ 직접 접근을 μ–΄λ ΅κ²Œ λ§Œλ“ λ‹€. 

    - private attribute : λ””버깅할 λ•Œ  보이지 μ•ŠλŠ”λ‹€. = λŸ°νƒ€μž„μ—μ„œ 보이지 μ•ŠλŠ”λ‹€.

     

    λ‹€μŒκ³Ό 같은 λ°©μ‹μœΌλ‘œ μ ‘κ·Όν•  수 μžˆλ‹€. 

    blink._Blink__password
    Out[93]: 'ilovejisso'

     

    πŸ“„ Getter/Setter λ©”μ„œλ“œ

    class Blink():
        def __init__(self, input_name, input_pw):
            self.name = input_name
            self.__password = input_pw
        def get_pw(self):
            print("inside the getter")
            return self.__password
        def set_pw(self, input_pw):
            print("inside the setter")
            self.__password = input_pw
    blink = Blink("Riri", "ilovelisa")
    
    blink.name
    Out[75]: 'Riri'
    
    blink.get_pw()
    inside the getter
    Out[76]: 'ilovelisa'
    
    blink.set_pw("ilovejennie")
    inside the setter
    
    blink.get_pw()
    inside the getter
    Out[78]: 'ilovejennie'

     

    πŸ“„ ν”„λ‘œνΌν‹° (@property)

    class Blink():
        def __init__(self, input_name, input_pw):
            self.name = input_name
            self.__password = input_pw
        @property
        def password(self):
            print("inside the getter")
            return self.__password
        @password.setter
        def password(self, input_pw):
            print("inside the setter")
            self.__password = input_pw
    blink = Blink("Riri", "ilovelisa")
    
    blink.name
    Out[89]: 'Riri'
    
    blink.password
    inside the getter
    Out[90]: 'ilovelisa'
    
    blink.password = "ilovejisso"
    inside the setter
    
    blink.password
    inside the getter
    Out[92]: 'ilovejisso'

     

    πŸ’‘ κ³„μ‚°λœ κ°’μ˜ ν”„λ‘œνΌν‹°

    ν”„λ‘œνΌν‹°λŠ” κ³„μ‚°λœ κ°’(computed value)λ₯Ό μ°Έμ‘°ν•  수 μžˆλ‹€. 

    class Circle:
        def __init__(self, radius):
            self.radius = radius
        @property
        def diameter(self):
            return 2 * self.radius
        
    c = Circle(5)
    
    c.radius
    Out[105]: 5
    
    c.diameter
    Out[106]: 10
    
    c.radius = 7
    c.diameter
    Out[108]: 14
    
    # seter propertyλ₯Ό λͺ…μ‹œν•˜μ§€ μ•ŠμœΌλ©΄ μ™ΈλΆ€λ‘œλΆ€ν„° 이 속성을 μ„€μ •ν•  수 μ—†λ‹€. 
    c.diameter = 28
    Traceback (most recent call last):
      File "C:\Anaconda\lib\site-packages\IPython\core\interactiveshell.py", line 3437, in run_code
        exec(code_obj, self.user_global_ns, self.user_ns)
      File "<ipython-input-109-23b5625e22cc>", line 1, in <module>
        c.diameter = 28
    AttributeError: can't set attribute

     

    πŸ“ λ©”μ„œλ“œ νƒ€μž…

    πŸ“„ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ

     

    πŸ“„ ν΄λž˜μŠ€ λ©”μ„œλ“œ

    @classmethod

    λ§€κ°œλ³€μˆ˜λ₯Ό cls둜 μ‚¬μš©

    class A:
        count = 0
        def __init__(self):
            A.count += 1
        def exclaim(self):
            print("I am an A!")
        @classmethod
        def kids(cls):
            print(f"A has {cls.count} little objects")
    easy_a = A()
    breezy_a = A()
    wheezy_a = A()
    
    A.kids()
    A has 3 little objects

     

     

    πŸ“„ μ •μ  λ©”μ„œλ“œ

    βœ”οΈ ν΄λž˜μŠ€λ₯Ό ν†΅ν•œ 객체 생성이 ν•„μš” μ—†λ‹€. 

         → 객체 생성은 무거운 μ—°μ‚°!!

    class CoyoteWeapon:
        @staticmethod
        def commercial():
            print("This coyoteweapon has been what?")
            
    CoyoteWeapon.commercial()
    This coyoteweapon has been what?

     

    πŸ“ λ•νƒ€μ΄ν•‘

    사림이 였리처럼 ν–‰λ™ν•˜λ©΄ 였리둜 봐도 λ¬΄λ°©ν•˜λ‹€λŠ” κ°œλ…

    βœ”οΈ νƒ€μž…을 미리 μ •ν•˜μ§€ μ•Šκ³  λŸ°νƒ€μž„에 ν•΄λ‹Ή λ©”μ†Œλ“œλ“€μ„ ν™•μΈν•˜λ©° κ²°μ •ν•œλ‹€. 

     

    πŸ’‘ λ‹€ν˜•μ„±

    ν•˜λ‚˜μ˜ 객체가 μ—¬λŸ¬ 가지 νƒ€μž…μ„ κ°€μ§ˆ 수 μžˆλŠ” 것

    νŒŒμ΄μ¬μ€ λ‹€ν˜•μ„±μ„ λŠμŠ¨ν•˜κ²Œ κ΅¬ν˜„ν•œλ‹€. 

    ν΄λž˜μŠ€μ— 상관 없이 같은 λ™μž‘μ„ λ‹€λ₯Έ 객체에 μ μš©ν•  수 μžˆλ‹€. 

    class Parrot:
        def fly(self):
            print("Parrot flying")
    class Airplane:
        def fly(self):
            print("Airplane flying")
    class Whale:
        def swim(self):
            print("Whale swimming")
    def lift_off(entity):
        entity.fly()

     

    βœ”οΈ λ‹€ λ‹€λ₯΄κ²Œ λ™μž‘ν•œλ‹€. 

    parrot = Parrot()
    airplane = Airplane()
    whale = Whale()
    
    lift_off(parrot) 
    Parrot flying
    
    lift_off(airplane)
    Airplane flying
    
    lift_off(whale)
    Traceback (most recent call last):
      File "C:\Anaconda\lib\site-packages\IPython\core\interactiveshell.py", line 3437, in run_code
        exec(code_obj, self.user_global_ns, self.user_ns)
      File "<ipython-input-12-d95e9c850c52>", line 1, in <module>
        lift_off(whale)
      File "<ipython-input-8-4c503ff8deae>", line 14, in lift_off
        entity.fly()
    AttributeError: 'Whale' object has no attribute 'fly'

     

    맀직 λ©”μ„œλ“œ

    __<func>__

     

    round ν•¨μˆ˜

    floor λ°”λ‹₯ ν•¨μˆ˜

    ceil 천μž₯ ν•¨μˆ˜

     

    μ• κ·Έλ¦¬κ²Œμ΄μ…˜ / μ½€νΌμ§€μ…˜

    상속을 톡해 κΈ°λŠ₯을 λ¬Όλ €λ°›λŠ”κ²ƒμ΄ μ•„λ‹Œ μ ‘κ·Ό 방법

     

    믹슀인

    닀쀑 μƒμ†μ˜ λ³΅μž‘μ„±μ„ ν•΄μ†Œν•˜κΈ° μœ„ν•œ 방법

    λŒ€μ²΄μ μœΌλ‘œ μ• κ·Έλ¦¬κ²Œμ΄μ…˜ / μ½€νΌμ§€μ…˜μ„ ν™œμš©

    믹슀인 (is-a) μ• κ·Έλ¦¬κ²Œμ΄μ…˜ / μ½€νΌμ§€μ…˜ (has-a)

     

    클래슀 내에 객체λ₯Ό μ‚½μž…

     

    λ„€μž„λ“œ νŠœν”Œ

    Dataclassκ°€ λ“±μž₯ν•˜κΈ° 전에 ν™œμš©λ˜λ˜ νƒ€μž…

     

     

     


    Ref.

    - 2021 μ²­λ…„μ·¨μ—… 아카데미 파이썬 μˆ˜μ—…

    - μ²˜μŒ μ‹œμž‘ν•˜λŠ” 파이썬, 빌 λˆ„λ°”λ…ΈλΉ…

     

    728x90
    λŒ“κΈ€
    곡지사항
    μ΅œκ·Όμ— 올라온 κΈ€