@property in Python

References: [์ฑ…] ํŒŒ์ด์ฌ ์ฝ”๋”ฉ์˜ ๊ธฐ์ˆ  - ๋ธŒ๋ › ์Šฌ๋ผํ‚จ ์ง€์Œ

Access Modifier

  • Python ์—๋Š” private ,public, protected, default ๋“ฑ์˜ keyword access modifier๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ณ , ์ž‘๋ช…๋ฒ• (naming)์œผ๋กœ ์ œ์–ดํ•œ๋‹ค

  • ํŒŒ์ด์ฌ์—์„œ ์„ ์–ธ๋˜๋Š” ๋ชจ๋“  variable๊ณผ method๋Š” public ์ด๊ธฐ ๋•Œ๋ฌธ์— getter ๋‚˜ setter method๊ฐ€ ์—†๋‹ค!

    • ์ฒซ ์–ธ์–ด๊ฐ€ Java์ธ ๋‚˜์—๊ฒŒ ์ƒˆ๋กœ์› ๋˜ Python ์˜ ํŠน์ง•!

    | public | protected | private | | ------------------ | ----------------------- | ------------------------ | | ์ ‘๋‘์‚ฌ์— ๋ฐ‘์ค„ ์—†์Œ | ์ ‘๋‘์‚ฌ์— ๋ฐ‘์ค„ ํ•œ ๊ฐœ (_) | ์ ‘๋‘์‚ฌ์— ๋ฐ‘์ค„ ๋‘ ๊ฐœ (__) |

    ex)

    class AcessModifiers:
        
        def __init__(self):
            pass
        
        def public(self):
            print('Public called!')
            
        def _protected(self):
            print('Protected called~~')
        
        def __private(self):
            print('Private called!!!')

Getters and Setters in Python

1. Get, Set method ์ง์ ‘ ๋งŒ๋“ค์–ด ๋ณด๊ธฐ

์ง์ ‘ ๊ตฌํ˜„

ex)

class Student:
    def __init__(self):
        self.__name = 'chloe'
    
    def get_name(self):
        return self.__name
    
    def set_name(self):
        return self.__name = name
  • ๊ฐ„๋‹จํ•˜์ง€๋งŒ Pythonic ํ•˜์ง€ ์•Š๋‹ค!

2. @property , @__.setter decorator ์‚ฌ์šฉํ•˜๊ธฐ

์ง์ ‘ ๊ตฌํ˜„ํ•  ๋•Œ ๋ณด๋‹ค ๋” ์ง๊ด€์ ์œผ๋กœ ํ‘œํ˜„ ๊ฐ€๋Šฅ!

property class๋ž€?

  • special descriptor object๋ฅผ ์ƒ์„ฑํ•˜๋Š” class

    • ๋‚ด๋ถ€์— getter, setter, deleter method๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Œ

      ex)

      p = property()
      
      print(p)
      print(p.getter)
      print(p.setter)
      print(p.deleter)

      ์‹คํ–‰ ๊ฒฐ๊ณผ

      image-20200726133346788

property decorator ์‚ฌ์šฉํ•˜๊ธฐ

  • Instance ๊ฐ์ฒด์˜ variable ์ ‘๊ทผ์„ method๋กœ ์ œ์•ฝํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” property ๊ฐ์ฒด๋กœ Instance ๊ฐ์ฒด์˜ variable์„ wrapping ํ•ด์•ผํ•จ

ex)

class Student:
    def __init__(self):
        self.__name = 'chloe'
    
    @property
    def name(self):
        return self.__name
    
    @name.setter
    def name(self, name):
        return self.__name = name

@property

  • getter์˜ ์—ญํ• 

  • method ์œ„์— @property decorator๋ฅผ ๋ถ™์ด๋ฉด ๋‚ด๋ถ€์ ์œผ๋กœ ํ•ด๋‹น method๋ช…์˜ instance๊ฐ€ ๋งŒ๋“ค์–ด์ง€๊ณ , ๊ทธ ๋‚ด๋ถ€์— ์ด method๊ฐ€ getter๋กœ ๋“ฑ๋ก๋จ

@[getter_method_name].setter

  • setter์˜ ์—ญํ• 

@property ๊ฐ€ setter๋ณด๋‹ค ์œ„์— ์žˆ์–ด์•ผ ํ•œ๋‹ค

  • @property ์—†์ด @ํ•จ์ˆ˜๋ช….setter ๋งŒ ์žˆ์œผ๋ฉด error๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค

  • but, setter ์—†์ด @property ๋งŒ ์‚ฌ์šฉํ•˜์—ฌ getter๋งŒ ์„ ์–ธ ํ•˜๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•˜๋‹ค

    • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ๊ธฐ ์ „์šฉ private data ๊ฐ€ ๋œ๋‹ค

3. @property decorator ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

์ œ๋Œ€๋กœ ๋Œ€๋‹ตํ•˜์ง€ ๋ชปํ•œ ๊ฒƒ์ด ๊ณ„์† ์ƒ๊ฐ๋‚˜์„œ ๋‹ค์‹œ ์ •๋ฆฌ,,,,ํ‘ํ‘ ์‹œ๊ฐ„์„ ๋Œ๋ฆฌ๊ณ ์‹ถ์—‰

  1. ์‚ฌ์šฉ์ž๊ฐ€ ์†์„ฑ์— ์ง์ ‘ ์ ‘๊ทผ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

    • Encapsulation ์„ ์œ„ํ•ด ์‚ฌ์šฉ

      • Class๋ฅผ ์ •์˜ํ•  ๋•Œ ๋‚ด๋ถ€์˜ ์†์„ฑ๊ณผ method๋ฅผ ๋ฌถ์–ด์„œ ํ•˜๋‚˜์˜ ๋‹จ์œ„๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ํ•˜๋‚˜์˜ ๋‹จ์œ„๋กœ ๋ฌถ์–ด์„œ class๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ Encapsulation์ด๋ผ๊ณ  ํ•œ๋‹ค

      • Class instance ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ณ€์ˆ˜๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ

        • why?

          • ์™ธ๋ถ€์—์„œ ๋ณ€์ˆ˜๋ฅผ ๋งˆ์Œ๋Œ€๋กœ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•˜๋ฉด, class ๊ฐ€ ์ •ํ•ด๋†“์€ logic๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๊ณ  error๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๊ธฐ ๋•Œ๋ฌธ

          • ๊ทธ๋ž˜์„œ OOP์—์„œ๋Š” Encapsulation ์„ ํ†ตํ•ด ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ณ€์ˆ˜์™€ ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ณ€์ˆ˜๋ฅผ ๊ตฌ๋ถ„ํ•œ๋‹ค!

  2. ๋‚˜์ค‘์— ์†์„ฑ์„ ์„ค์ •ํ•  ๋•Œ ํŠน๋ณ„ํ•œ ๋™์ž‘์ด ์ผ์–ด๋‚˜์•ผ ํ•˜๋ฉด

  3. ๋ถ€๋ชจ class์˜ ์†์„ฑ์„ ๋ถˆ๋ณ€ (immutable) ์œผ๋กœ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ

    ex)

    class FixedResistance(Resistor):
        # ...
        @property
        def data(self):
            return self.__data
        
        @data.setter
        def data(self, data):
            if hasattr(self, '__data'):
                raise AttributeError('You are not allowed to set attribute!')
            self.__data = data
    • ์œ„์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  property์— ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•˜๋ฉด error๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ ํ™•์ธ ๊ฐ€๋Šฅ

4. Better way to use @property

  • @property method๋กœ getter, setter๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ ํ•จ

    • getter @property method์—์„œ ๋‹ค๋ฅธ attribute๋ฅผ ์„ค์ •ํ•˜์ง€ ๋ง์•„์•ผ ํ•จ

      • @property.setter method ์—์„œ๋งŒ ๊ด€๋ จ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ!!

  • ์žฌ์‚ฌ์šฉ์„ฑ ์€ ํŒŒ์ด์ฌ์— ๋‚ด์žฅ๋œ @property ์˜ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ์ 

    • @property๋กœ decorate ํ•˜๋Š” method๋ฅผ ๊ฐ™์€ class์— ์†ํ•œ ์—ฌ๋Ÿฌ ์†์„ฑ์—์„œ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์—†๋‹ค

      + ๊ด€๋ จ ์—†๋Š” class์—์„œ๋„ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์—†๋‹ค

    • ๊ทธ๋ž˜์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ @property method์—์„œ๋Š” descriptor protocol ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค

+

Descriptor Protocol

  • Descriptor class๋Š” ๋ฐ˜๋ณต ์ฝ”๋“œ ์—†์ด๋„ method๋ฅผ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” __get__ ๊ณผ __set__ method ๋ฅผ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ๋‹ค

  • ํ•˜๋‚˜์˜ class์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋งŽ์€ ์†์„ฑ์— ๊ฐ™์€ logic์„ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค

Last updated

Was this helpful?