๊ณ์ฐ๋ ์์ฑ, ์์ฑ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฐ ๊ณ ๊ธ ๊ฐ์ฒด ์งํฅ ์ค๊ณ๋ฅผ ์ํ Python property descriptor๋ฅผ ๋ง์คํฐํ์ธ์. ์ค์ฉ์ ์ธ ์์ ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ํตํด ๋ฐฐ์ฐ์ญ์์ค.
Python Property Descriptor: ๊ณ์ฐ๋ ์์ฑ ๋ฐ ์ ํจ์ฑ ๊ฒ์ฌ ๋ก์ง
Python property descriptor๋ ํด๋์ค ๋ด์์ ์์ฑ ์ ๊ทผ ๋ฐ ๋์์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฅผ ํตํด ์์ฑ์ ๊ฐ์ ธ์ค๊ณ , ์ค์ ํ๊ณ , ์ญ์ ํ๊ธฐ ์ํ ์ฌ์ฉ์ ์ ์ ๋ก์ง์ ์ ์ํ์ฌ ๊ณ์ฐ๋ ์์ฑ์ ๋ง๋ค๊ณ , ์ ํจ์ฑ ๊ฒ์ฌ ๊ท์น์ ์ ์ฉํ๊ณ , ๊ณ ๊ธ ๊ฐ์ฒด ์งํฅ ๋์์ธ ํจํด์ ๊ตฌํํ ์ ์์ต๋๋ค. ์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋์์๋ property descriptor์ ๋ชจ๋ ๊ฒ์ ์ดํด๋ณด๊ณ ์ด ํ์์ ์ธ Python ๊ธฐ๋ฅ์ ๋ง์คํฐํ๋ ๋ฐ ๋์์ด ๋๋ ์ค์ฉ์ ์ธ ์์ ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ ๊ณตํฉ๋๋ค.
Property Descriptor๋ ๋ฌด์์ ๋๊น?
Python์์ descriptor๋ "๋ฐ์ธ๋ฉ ๋์"์ ๊ฐ๋ ๊ฐ์ฒด ์์ฑ์
๋๋ค. ์ฆ, ํด๋น ์์ฑ ์ ๊ทผ์ด descriptor ํ๋กํ ์ฝ์ ๋ฉ์๋์ ์ํด ์ฌ์ ์๋์์ต๋๋ค. ์ด๋ฌํ ๋ฉ์๋๋ __get__()
, __set__()
๋ฐ __delete__()
์
๋๋ค. ์ด๋ฌํ ๋ฉ์๋ ์ค ํ๋๋ผ๋ ์์ฑ์ ๋ํด ์ ์๋๋ฉด descriptor๊ฐ ๋ฉ๋๋ค. ํนํ property descriptor๋ ์ฌ์ฉ์ ์ ์ ๋ก์ง์ผ๋ก ์์ฑ ์ ๊ทผ์ ๊ด๋ฆฌํ๋๋ก ์ค๊ณ๋ ํน์ ์ ํ์ descriptor์
๋๋ค.
Descriptor๋ properties, ๋ฉ์๋, static ๋ฉ์๋, class ๋ฉ์๋ ๋ฐ super()
๋ฅผ ํฌํจํ์ฌ ๋ง์ ๋ด์ฅ Python ๊ธฐ๋ฅ์์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ฌ์ฉ๋๋ ์ ์์ค ๋ฉ์ปค๋์ฆ์
๋๋ค. Descriptor๋ฅผ ์ดํดํ๋ฉด ๋์ฑ ์ ๊ตํ๊ณ Pythonicํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
Descriptor ํ๋กํ ์ฝ
Descriptor ํ๋กํ ์ฝ์ ์์ฑ ์ ๊ทผ์ ์ ์ดํ๋ ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค.
__get__(self, instance, owner)
: descriptor์ ๊ฐ์ ๊ฒ์ํ ๋ ํธ์ถ๋ฉ๋๋ค.instance
๋ descriptor๋ฅผ ํฌํจํ๋ ํด๋์ค์ ์ธ์คํด์ค์ด๊ณ ,owner
๋ ํด๋์ค ์์ฒด์ ๋๋ค. descriptor๊ฐ ํด๋์ค์์ ์ ๊ทผ๋๋ ๊ฒฝ์ฐ(์:MyClass.my_descriptor
),instance
๋None
์ด ๋ฉ๋๋ค.__set__(self, instance, value)
: descriptor์ ๊ฐ์ด ์ค์ ๋ ๋ ํธ์ถ๋ฉ๋๋ค.instance
๋ ํด๋์ค์ ์ธ์คํด์ค์ด๊ณ ,value
๋ ํ ๋น๋๋ ๊ฐ์ ๋๋ค.__delete__(self, instance)
: descriptor์ ์์ฑ์ด ์ญ์ ๋ ๋ ํธ์ถ๋ฉ๋๋ค.instance
๋ ํด๋์ค์ ์ธ์คํด์ค์ ๋๋ค.
property descriptor๋ฅผ ๋ง๋ค๋ ค๋ฉด ์ด๋ฌํ ๋ฉ์๋ ์ค ํ๋ ์ด์์ ๊ตฌํํ๋ ํด๋์ค๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค. ๊ฐ๋จํ ์์ ๋ถํฐ ์์ํ๊ฒ ์ต๋๋ค.
๊ธฐ๋ณธ Property Descriptor ๋ง๋ค๊ธฐ
๋ค์์ ์์ฑ์ ๋๋ฌธ์๋ก ๋ณํํ๋ property descriptor์ ๊ธฐ๋ณธ ์์ ์ ๋๋ค.
class UppercaseDescriptor:
def __get__(self, instance, owner):
if instance is None:
return self # ํด๋์ค์์ ์ ๊ทผํ ๋ descriptor ์์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
return instance._my_attribute.upper() # "๋น๊ณต๊ฐ" ์์ฑ์ ์ ๊ทผํฉ๋๋ค.
def __set__(self, instance, value):
instance._my_attribute = value
class MyClass:
my_attribute = UppercaseDescriptor()
def __init__(self, value):
self._my_attribute = value # "๋น๊ณต๊ฐ" ์์ฑ์ ์ด๊ธฐํํฉ๋๋ค.
# ์ฌ์ฉ ์
obj = MyClass("hello")
print(obj.my_attribute) # ์ถ๋ ฅ: HELLO
obj.my_attribute = "world"
print(obj.my_attribute) # ์ถ๋ ฅ: WORLD
์ด ์์ ์์:
UppercaseDescriptor
๋__get__()
๋ฐ__set__()
์ ๊ตฌํํ๋ descriptor ํด๋์ค์ ๋๋ค.MyClass
๋UppercaseDescriptor
์ ์ธ์คํด์ค์ธ ์์ฑmy_attribute
๋ฅผ ์ ์ํฉ๋๋ค.obj.my_attribute
์ ์ ๊ทผํ๋ฉดUppercaseDescriptor
์__get__()
๋ฉ์๋๊ฐ ํธ์ถ๋์ด ๊ธฐ๋ณธ_my_attribute
๋ฅผ ๋๋ฌธ์๋ก ๋ณํํฉ๋๋ค.obj.my_attribute
๋ฅผ ์ค์ ํ๋ฉด__set__()
๋ฉ์๋๊ฐ ํธ์ถ๋์ด ๊ธฐ๋ณธ_my_attribute
๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
"๋น๊ณต๊ฐ" ์์ฑ(_my_attribute
)์ ์ฌ์ฉ์ ์ ์ํ์ญ์์ค. ์ด๋ ์์ฑ์ด ํด๋์ค ๋ด์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํ ๊ฒ์ด๋ฉฐ ์ธ๋ถ์์ ์ง์ ์ ๊ทผํด์๋ ์ ๋๋ค๋ ๊ฒ์ ๋ํ๋ด๋ Python์ ์ผ๋ฐ์ ์ธ ๊ท์น์
๋๋ค. Descriptor๋ ์ด๋ฌํ "๋น๊ณต๊ฐ" ์์ฑ์ ๋ํ ์ ๊ทผ์ ์กฐ์ ํ๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค.
๊ณ์ฐ๋ ์์ฑ
Property descriptor๋ ๊ณ์ฐ๋ ์์ฑ์ ๋ง๋๋ ๋ฐ ์ ํฉํฉ๋๋ค. ๊ณ์ฐ๋ ์์ฑ์ ๊ฐ์ด ๋ค๋ฅธ ์์ฑ์ ๊ธฐ๋ฐ์ผ๋ก ๋์ ์ผ๋ก ๊ณ์ฐ๋๋ ์์ฑ์ ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ผ๊ด์ฑ ์๊ฒ ์ ์งํ๊ณ ์ฝ๋๋ฅผ ๋์ฑ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ํตํ ๋ณํ๊ณผ ๊ด๋ จ๋ ์์ ๋ฅผ ๊ณ ๋ คํด ๋ณด๊ฒ ์ต๋๋ค(๋ฐ๋ชจ๋ฅผ ์ํด ๊ฐ์ ๋ณํ์จ ์ฌ์ฉ).
class CurrencyConverter:
def __init__(self, usd_to_eur_rate, usd_to_gbp_rate):
self.usd_to_eur_rate = usd_to_eur_rate
self.usd_to_gbp_rate = usd_to_gbp_rate
class Money:
def __init__(self, usd, converter):
self.usd = usd
self.converter = converter
class EURDescriptor:
def __get__(self, instance, owner):
if instance is None:
return self
return instance.usd * instance.converter.usd_to_eur_rate
def __set__(self, instance, value):
raise AttributeError("EUR์ ์ง์ ์ค์ ํ ์ ์์ต๋๋ค. ๋์ USD๋ฅผ ์ค์ ํ์ธ์.")
class GBPDescriptor:
def __get__(self, instance, owner):
if instance is None:
return self
return instance.usd * instance.converter.usd_to_gbp_rate
def __set__(self, instance, value):
raise AttributeError("GBP๋ฅผ ์ง์ ์ค์ ํ ์ ์์ต๋๋ค. ๋์ USD๋ฅผ ์ค์ ํ์ธ์.")
eur = EURDescriptor()
gbp = GBPDescriptor()
# ์ฌ์ฉ ์
converter = CurrencyConverter(0.85, 0.75) # USD์์ EUR ๋ฐ USD์์ GBP๋ก์ ํ์จ
money = Money(100, converter)
print(f"USD: {money.usd}")
print(f"EUR: {money.eur}")
print(f"GBP: {money.gbp}")
# EUR ๋๋ GBP๋ฅผ ์ค์ ํ๋ ค๊ณ ํ๋ฉด AttributeError๊ฐ ๋ฐ์ํฉ๋๋ค.
# money.eur = 90 # ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ด ์์ ์์:
CurrencyConverter
๋ ํ์จ์ ๋ณด์ ํฉ๋๋ค.Money
๋ USD๋ก ํ์๋ ๊ธ์ก์ ๋ํ๋ด๋ฉฐCurrencyConverter
์ธ์คํด์ค์ ๋ํ ์ฐธ์กฐ๋ฅผ ๊ฐ์ต๋๋ค.EURDescriptor
๋ฐGBPDescriptor
๋ USD ๊ฐ๊ณผ ํ์จ์ ๊ธฐ๋ฐ์ผ๋ก EUR ๋ฐ GBP ๊ฐ์ ๊ณ์ฐํ๋ descriptor์ ๋๋ค.eur
๋ฐgbp
์์ฑ์ ์ด๋ฌํ descriptor์ ์ธ์คํด์ค์ ๋๋ค.__set__()
๋ฉ์๋๋ ๊ณ์ฐ๋ EUR ๋ฐ GBP ๊ฐ์ ์ง์ ์์ ์ ๋ฐฉ์งํ๊ธฐ ์ํดAttributeError
๋ฅผ ๋ฐ์์ํต๋๋ค. ์ด๋ฅผ ํตํด USD ๊ฐ์ ํตํด ๋ณ๊ฒฝ์ด ์ด๋ฃจ์ด์ ธ ์ผ๊ด์ฑ์ด ์ ์ง๋ฉ๋๋ค.
์์ฑ ์ ํจ์ฑ ๊ฒ์ฌ
Property descriptor๋ ์์ฑ ๊ฐ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ ๊ท์น์ ์ ์ฉํ๋ ๋ฐ์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๊ณ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด๋ฉ์ผ ์ฃผ์์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ descriptor๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ์์ ๋ฅผ ์ํด ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ๊ฐ๋จํ๊ฒ ์ ์งํ๊ฒ ์ต๋๋ค.
import re
class EmailDescriptor:
def __init__(self, attribute_name):
self.attribute_name = attribute_name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__[self.attribute_name]
def __set__(self, instance, value):
if not self.is_valid_email(value):
raise ValueError(f"์ ํจํ์ง ์์ ์ด๋ฉ์ผ ์ฃผ์: {value}")
instance.__dict__[self.attribute_name] = value
def __delete__(self, instance):
del instance.__dict__[self.attribute_name]
def is_valid_email(self, email):
# ๊ฐ๋จํ ์ด๋ฉ์ผ ์ ํจ์ฑ ๊ฒ์ฌ (๊ฐ์ ๋ ์ ์์)
pattern = r"^[\w\.-]+@([\w-]+\.)+[\w-]{2,4}$"
return re.match(pattern, email) is not None
class User:
email = EmailDescriptor("email")
def __init__(self, email):
self.email = email
# ์ฌ์ฉ ์
user = User("test@example.com")
print(user.email)
# ์ ํจํ์ง ์์ ์ด๋ฉ์ผ์ ์ค์ ํ๋ ค๊ณ ํ๋ฉด ValueError๊ฐ ๋ฐ์ํฉ๋๋ค.
# user.email = "invalid-email" # ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
try:
user.email = "invalid-email"
except ValueError as e:
print(e)
์ด ์์ ์์:
EmailDescriptor
๋ ์ ๊ท์(is_valid_email
)์ ์ฌ์ฉํ์ฌ ์ด๋ฉ์ผ ์ฃผ์์ ์ ํจ์ฑ์ ๊ฒ์ฌํฉ๋๋ค.__set__()
๋ฉ์๋๋ ๊ฐ์ ํ ๋นํ๊ธฐ ์ ์ ๊ฐ์ด ์ ํจํ ์ด๋ฉ์ผ์ธ์ง ํ์ธํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉดValueError
๋ฅผ ๋ฐ์์ํต๋๋ค.User
ํด๋์ค๋EmailDescriptor
๋ฅผ ์ฌ์ฉํ์ฌemail
์์ฑ์ ๊ด๋ฆฌํฉ๋๋ค.- descriptor๋ ๊ฐ์ ์ธ์คํด์ค์
__dict__
์ ์ง์ ์ ์ฅํ์ฌ descriptor๋ฅผ ๋ค์ ํธ๋ฆฌ๊ฑฐํ์ง ์๊ณ ์ ๊ทผํ ์ ์์ต๋๋ค(๋ฌดํ ์ฌ๊ท ๋ฐฉ์ง).
์ด๋ ๊ฒ ํ๋ฉด ์ ํจํ ์ด๋ฉ์ผ ์ฃผ์๋ง email
์์ฑ์ ํ ๋น๋ ์ ์์ด ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ด ํฅ์๋ฉ๋๋ค. is_valid_email
ํจ์๋ ๊ธฐ๋ณธ์ ์ธ ์ ํจ์ฑ ๊ฒ์ฌ๋ง ์ ๊ณตํ๋ฉฐ ํ์ํ ๊ฒฝ์ฐ ๊ตญ์ ํ๋ ์ด๋ฉ์ผ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ํด ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ณด๋ค ๊ฐ๋ ฅํ ๊ฒ์ฌ๋ฅผ ์ํด ๊ฐ์ ๋ ์ ์์ต๋๋ค.
`property` ๋ด์ฅ ํจ์ ์ฌ์ฉ
Python์ ๊ฐ๋จํ property descriptor ์์ฑ์ ๋จ์ํํ๋ property()
๋ผ๋ ๋ด์ฅ ํจ์๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก descriptor ํ๋กํ ์ฝ์ ๋ํํ๋ ํธ๋ฆฌํ ๋ํผ์
๋๋ค. ๊ธฐ๋ณธ์ ์ธ ๊ณ์ฐ๋ ์์ฑ์ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค.
class Rectangle:
def __init__(self, width, height):
self._width = width
self._height = height
def get_area(self):
return self._width * self._height
def set_area(self, area):
# ๋ฉด์ ์์ ๋๋น/๋์ด๋ฅผ ๊ณ์ฐํ๋ ๋ก์ง์ ๊ตฌํํฉ๋๋ค.
# ๊ฐ๋จํ๊ฒํ๊ธฐ ์ํด ๋๋น์ ๋์ด๋ฅผ ์ ๊ณฑ๊ทผ์ผ๋ก ์ค์ ํฉ๋๋ค.
import math
side = math.sqrt(area)
self._width = side
self._height = side
def delete_area(self):
self._width = 0
self._height = 0
area = property(get_area, set_area, delete_area, "์ฌ๊ฐํ์ ๋ฉด์ ")
# ์ฌ์ฉ ์
rect = Rectangle(5, 10)
print(rect.area) # ์ถ๋ ฅ: 50
rect.area = 100
print(rect._width) # ์ถ๋ ฅ: 10.0
print(rect._height) # ์ถ๋ ฅ: 10.0
del rect.area
print(rect._width) # ์ถ๋ ฅ: 0
print(rect._height) # ์ถ๋ ฅ: 0
์ด ์์ ์์:
property()
๋ ์ต๋ 4๊ฐ์ ์ธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.fget
(getter),fset
(setter),fdel
(deleter) ๋ฐdoc
(docstring).area
๋ฅผ ๊ฐ์ ธ์ค๊ณ , ์ค์ ํ๊ณ , ์ญ์ ํ๊ธฐ ์ํ ๋ณ๋์ ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค.property()
๋ ์ด๋ฌํ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ ์ ๊ทผ์ ๊ด๋ฆฌํ๋ property descriptor๋ฅผ ๋ง๋ญ๋๋ค.
property
๋ด์ฅ ํจ์๋ ๋ณ๋์ descriptor ํด๋์ค๋ฅผ ๋ง๋๋ ๊ฒ๋ณด๋ค ๊ฐ๋จํ ๊ฒฝ์ฐ์ ๋ ์ฝ๊ธฐ ์ฝ๊ณ ๊ฐ๊ฒฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋ณต์กํ ๋ก์ง์ด๋ ์ฌ๋ฌ ์์ฑ ๋๋ ํด๋์ค์์ descriptor ๋ก์ง์ ์ฌ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ์๋ ์ฌ์ฉ์ ์ ์ descriptor ํด๋์ค๋ฅผ ๋ง๋ค๋ฉด ๋ ๋์ ๊ตฌ์ฑ ๋ฐ ์ฌ์ฌ์ฉ์ฑ์ ์ ๊ณตํฉ๋๋ค.
Property Descriptor๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ
Property descriptor๋ ๊ฐ๋ ฅํ ๋๊ตฌ์ด์ง๋ง ์ ์คํ๊ฒ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋ค์์ ํนํ ์ ์ฉํ ์๋๋ฆฌ์ค์ ๋๋ค.
- ๊ณ์ฐ๋ ์์ฑ: ์์ฑ ๊ฐ์ด ๋ค๋ฅธ ์์ฑ ๋๋ ์ธ๋ถ ์์ธ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๊ณ ๋์ ์ผ๋ก ๊ณ์ฐํด์ผ ํ๋ ๊ฒฝ์ฐ.
- ์์ฑ ์ ํจ์ฑ ๊ฒ์ฌ: ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๊ธฐ ์ํด ์์ฑ ๊ฐ์ ๋ํ ํน์ ๊ท์น ๋๋ ์ ์ฝ ์กฐ๊ฑด์ ์ ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ.
- ๋ฐ์ดํฐ ์บก์ํ: ์์ฑ์ ์ ๊ทผํ๊ณ ์์ ํ๋ ๋ฐฉ๋ฒ์ ์ ์ดํ๊ณ ๊ธฐ๋ณธ ๊ตฌํ ์ธ๋ถ ์ ๋ณด๋ฅผ ์จ๊ธฐ๋ ค๋ ๊ฒฝ์ฐ.
- ์ฝ๊ธฐ ์ ์ฉ ์์ฑ: ์ด๊ธฐํ๋ ํ ์์ฑ ์์ ์ ๋ฐฉ์งํ๋ ค๋ ๊ฒฝ์ฐ(
__get__
๋ฉ์๋๋ง ์ ์ํ์ฌ). - ์ง์ฐ ๋ก๋ฉ: ์์ฑ ๊ฐ์ ์ฒ์ ์ ๊ทผํ ๋๋ง ๋ก๋ํ๋ ค๋ ๊ฒฝ์ฐ(์: ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ ๋ก๋).
- ์ธ๋ถ ์์คํ ๊ณผ ํตํฉ: Descriptor๋ ๊ฐ์ฒด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค/API์ ๊ฐ์ ์ธ๋ถ ์์คํ ๊ฐ์ ์ถ์ํ ๊ณ์ธต์ผ๋ก ์ฌ์ฉ๋ ์ ์์ผ๋ฏ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ด ๊ธฐ๋ณธ ํํ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด์์ฑ์ด ํฅ์๋ฉ๋๋ค. Date๋ฅผ ์ ์ฅํ๋ ์์ฑ์ด ์์ง๋ง ๊ธฐ๋ณธ ์คํ ๋ฆฌ์ง๋ ํ๋ซํผ์ ๋ฐ๋ผ ๋ค๋ฅผ ์ ์๋ค๊ณ ์์ํด๋ณด์ญ์์ค. Descriptor๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์ถ์ํํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ property descriptor๋ฅผ ๋ถํ์ํ๊ฒ ์ฌ์ฉํ์ง ๋ง์ญ์์ค. ์ฝ๋๊ฐ ๋ณต์กํด์ง ์ ์์ต๋๋ค. ํน์ ๋ก์ง ์์ด ๊ฐ๋จํ ์์ฑ ์ ๊ทผ์ ๊ฒฝ์ฐ ์ง์ ์์ฑ ์ ๊ทผ์ผ๋ก๋ ์ถฉ๋ถํ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. Descriptor๋ฅผ ๊ณผ๋ํ๊ฒ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ์ดํดํ๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ๊ฐ ๋ ์ด๋ ค์์ง ์ ์์ต๋๋ค.
๋ชจ๋ฒ ์ฌ๋ก
Property descriptor๋ฅผ ์ฌ์ฉํ ๋ ๋ช ์ฌํด์ผ ํ ๋ช ๊ฐ์ง ๋ชจ๋ฒ ์ฌ๋ก๊ฐ ์์ต๋๋ค.
- "๋น๊ณต๊ฐ" ์์ฑ ์ฌ์ฉ: ์ด๋ฆ ์ถฉ๋์ ๋ฐฉ์งํ๊ณ ํด๋์ค ์ธ๋ถ์์ ์ง์ ์ ๊ทผํ์ง ๋ชปํ๋๋ก ๊ธฐ๋ณธ ๋ฐ์ดํฐ๋ฅผ "๋น๊ณต๊ฐ" ์์ฑ(์:
_my_attribute
)์ ์ ์ฅํฉ๋๋ค. instance is None
์ฒ๋ฆฌ:__get__()
๋ฉ์๋์์instance
๊ฐNone
์ธ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ด๋ descriptor๊ฐ ์ธ์คํด์ค ์์ฒด๊ฐ ์๋ ํด๋์ค์์ ์ ๊ทผ๋ ๋ ๋ฐ์ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ descriptor ๊ฐ์ฒด ์์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.- ์ ์ ํ ์์ธ ๋ฐ์: ์ ํจ์ฑ ๊ฒ์ฌ์ ์คํจํ๊ฑฐ๋ ์์ฑ ์ค์ ์ด ํ์ฉ๋์ง ์๋ ๊ฒฝ์ฐ ์ ์ ํ ์์ธ(์:
ValueError
,TypeError
,AttributeError
)๋ฅผ ๋ฐ์์ํต๋๋ค. - Descriptor ๋ฌธ์ํ: descriptor ํด๋์ค ๋ฐ ์์ฑ์ docstring์ ์ถ๊ฐํ์ฌ ๋ชฉ์ ๊ณผ ์ฌ์ฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค.
- ์ฑ๋ฅ ๊ณ ๋ ค: ๋ณต์กํ descriptor ๋ก์ง์ ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค. ์ฝ๋๋ฅผ ํ๋กํ์ผ๋งํ์ฌ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์๋ณํ๊ณ descriptor๋ฅผ ์ ์ ํ๊ฒ ์ต์ ํํฉ๋๋ค.
- ์ฌ๋ฐ๋ฅธ ์ ๊ทผ ๋ฐฉ์ ์ ํ: ๋ก์ง์ ๋ณต์ก์ฑ๊ณผ ์ฌ์ฌ์ฉ ํ์์ฑ์ ๋ฐ๋ผ
property
๋ด์ฅ ํจ์ ๋๋ ์ฌ์ฉ์ ์ ์ descriptor ํด๋์ค๋ฅผ ์ฌ์ฉํ ์ง ๊ฒฐ์ ํฉ๋๋ค. - ๊ฐ๋จํ๊ฒ ์ ์ง: ๋ค๋ฅธ ์ฝ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณต์ก์ฑ์ ํผํด์ผ ํฉ๋๋ค. Descriptor๋ ๋์์ธ ํ์ง์ ๊ฐ์ ํด์ผ ํ๋ฉฐ ๋๋ ํํด์๋ ์ ๋ฉ๋๋ค.
๊ณ ๊ธ Descriptor ๊ธฐ์
๊ธฐ๋ณธ ์ฌํญ ์ธ์๋ property descriptor๋ ๋ ๊ณ ๊ธ ๊ธฐ์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ๋น๋ฐ์ดํฐ Descriptor:
__get__()
๋ฉ์๋๋ง ์ ์ํ๋ descriptor๋ฅผ ๋น๋ฐ์ดํฐ descriptor(๋๋ ๋๋ก๋ "์๋์" descriptor)๋ผ๊ณ ํฉ๋๋ค. ์ธ์คํด์ค ์์ฑ๋ณด๋ค ์ฐ์ ์์๊ฐ ๋ฎ์ต๋๋ค. ๋์ผํ ์ด๋ฆ์ ์ธ์คํด์ค ์์ฑ์ด ์๋ ๊ฒฝ์ฐ ๋น๋ฐ์ดํฐ descriptor๋ฅผ ์๋์ํฉ๋๋ค. ์ด๋ ๊ธฐ๋ณธ๊ฐ์ ์ ๊ณตํ๊ฑฐ๋ ์ง์ฐ ๋ก๋ฉ ๋์์ ์ ์ฉํ ์ ์์ต๋๋ค. - ๋ฐ์ดํฐ Descriptor:
__set__()
๋๋__delete__()
๋ฅผ ์ ์ํ๋ descriptor๋ฅผ ๋ฐ์ดํฐ descriptor๋ผ๊ณ ํฉ๋๋ค. ์ธ์คํด์ค ์์ฑ๋ณด๋ค ์ฐ์ ์์๊ฐ ๋์ต๋๋ค. ์์ฑ์ ์ ๊ทผํ๊ฑฐ๋ ํ ๋นํ๋ฉด ํญ์ descriptor ๋ฉ์๋๊ฐ ํธ๋ฆฌ๊ฑฐ๋ฉ๋๋ค. - Descriptor ๊ฒฐํฉ: ์ฌ๋ฌ descriptor๋ฅผ ๊ฒฐํฉํ์ฌ ๋ ๋ณต์กํ ๋์์ ๋ง๋ค ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์์ฑ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๊ณ ๋ณํํ๋ descriptor๊ฐ ์์ ์ ์์ต๋๋ค.
- Metaclass: Descriptor๋ Metaclass์ ๊ฐ๋ ฅํ๊ฒ ์ํธ ์์ฉํฉ๋๋ค. ์ฌ๊ธฐ์ properties๋ metaclass์ ์ํด ํ ๋น๋๊ณ ์์ฑํ๋ ํด๋์ค์ ์ํด ์์๋ฉ๋๋ค. ์ด๋ฅผ ํตํด ๋งค์ฐ ๊ฐ๋ ฅํ ๋์์ธ์ด ๊ฐ๋ฅํ์ฌ Descriptor๋ฅผ ํด๋์ค์์ ์ฌ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Descriptor ํ ๋น์ ์๋ํํ ์๋ ์์ต๋๋ค.
์ ์ญ ๊ณ ๋ ค ์ฌํญ
Property descriptor๋ก ์ค๊ณํ ๋, ํนํ ์ ์ญ ์ปจํ ์คํธ์์ ๋ค์ ์ฌํญ์ ์ ์ํ์ญ์์ค.
- ์ง์ญํ: ๋ก์บ์ ๋ฐ๋ผ ๋ฐ์ดํฐ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ ๊ฒฝ์ฐ(์: ์ฐํธ ๋ฒํธ, ์ ํ ๋ฒํธ) ๋ค๋ฅธ ์ง์ญ ๋ฐ ํ์์ ์ง์ํ๋ ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ญ์์ค.
- ์๊ฐ๋: ๋ ์ง ๋ฐ ์๊ฐ์ผ๋ก ์์
ํ ๋ ์๊ฐ๋๋ฅผ ์ผ๋์ ๋๊ณ
pytz
์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ณํ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ์ญ์์ค. - ํตํ: ํตํ ๊ฐ์ผ๋ก ์์ ํ๋ ๊ฒฝ์ฐ ๋ค๋ฅธ ํตํ ๋ฐ ํ์จ์ ์ง์ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ญ์์ค. ํ์ค ํตํ ํ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
- ๋ฌธ์ ์ธ์ฝ๋ฉ: ํนํ ๋ฌธ์์ด์ ์ ํจ์ฑ์ ๊ฒ์ฌํ ๋ ์ฝ๋๊ฐ ๋ค๋ฅธ ๋ฌธ์ ์ธ์ฝ๋ฉ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํ์ญ์์ค.
- ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ ํ์ค: ์ผ๋ถ ์ง์ญ์๋ ํน์ ๋ฒ์ ๋๋ ๊ท์ ์ ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ ์๊ตฌ ์ฌํญ์ด ์์ต๋๋ค. ์ด๋ฅผ ์ธ์ํ๊ณ descriptor๊ฐ ์ด๋ฅผ ์ค์ํ๋์ง ํ์ธํ์ญ์์ค.
- ์ ๊ทผ์ฑ: Properties๋ ํต์ฌ ๋์์ธ์ ๋ณ๊ฒฝํ์ง ์๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ค์ํ ์ธ์ด์ ๋ฌธํ์ ์ ์ํ ์ ์๋๋ก ์ค๊ณํด์ผ ํฉ๋๋ค.
๊ฒฐ๋ก
Python property descriptor๋ ์์ฑ ์ ๊ทผ ๋ฐ ๋์์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฐ๋ ฅํ๊ณ ๋ค์ฌ๋ค๋ฅํ ๋๊ตฌ์ ๋๋ค. ์ด๋ฅผ ํตํด ๊ณ์ฐ๋ ์์ฑ์ ๋ง๋ค๊ณ , ์ ํจ์ฑ ๊ฒ์ฌ ๊ท์น์ ์ ์ฉํ๊ณ , ๊ณ ๊ธ ๊ฐ์ฒด ์งํฅ ๋์์ธ ํจํด์ ๊ตฌํํ ์ ์์ต๋๋ค. descriptor ํ๋กํ ์ฝ์ ์ดํดํ๊ณ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ๋์ฑ ์ ๊ตํ๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด Python ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํตํ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ณด์ฅ์์ ์จ๋๋งจ๋ ํ์ ๊ฐ ๊ณ์ฐ์ ์ด๋ฅด๊ธฐ๊น์ง property descriptor๋ Python ํด๋์ค์์ ์์ฑ ์ฒ๋ฆฌ๋ฅผ ์ฌ์ฉ์ ์ ์ํ๋ ์ฐ์ํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ๋ง์คํฐํ๋ฉด Python์ ๊ฐ์ฒด ๋ชจ๋ธ์ ๋ํ ๋ ๊น์ ์ดํด๊ฐ ๊ฐ๋ฅํ๊ณ ๋์ฑ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
property
๋๋ ์ฌ์ฉ์ ์ ์ descriptor๋ฅผ ์ฌ์ฉํ๋ฉด Python ๊ธฐ์ ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค.