I'm implementing a class in Python which has many properties. Here's an example of a property:
class Test:
def __init__(self):
self._value = None
def get_value(self):
if self._value is None:
self._value = datetime.datetime.now()
return self._value
def set_value(self, new_value):
self._value = new_value
value = property(get_value, set_value)
This seems like a lot of code.
Is there a more concise way to implement this pattern? I'm using PyCharm if that makes any difference.
CodePudding user response:
If you have same logic/validation for some of your properties you can write your own descriptor(Properties are descriptors).
Here for example I accept only string with length higher than 3. Instead of two properties, one for first_name
and one for last_name
, I created a descriptor ValidName
and use it for both first_name
and last_name
:
class ValidName:
def __set_name__(self, owner, name):
self.name = f"_{name}"
def __set__(self, instance, value):
if len(value) < 3:
raise ValueError("The lenght must be larger than 3.")
setattr(instance, self.name, value)
def __get__(self, instance, owner):
return getattr(instance, self.name)
class Person:
first_name = ValidName()
last_name = ValidName()
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
CodePudding user response:
You can use the property
decorator:
class Test:
def __init__(self):
self._value = None
@property
def value(self):
if self._value is None:
self._value = datetime.datetime.now()
return self._value
Of course, you could also get almost the same behavior in this case by writing:
def __init__(self):
self.value = datetime.datetime.now()
The difference being that the solution with @property
will be read-only by default (see the docs on adding setter and deleter methods), while the latter solution creats a read/write attribute.