Home > Back-end >  Python: concise properties
Python: concise properties

Time:02-10

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.

  • Related