Praind
Praind

Reputation: 1571

Shorter way to make properties read-only

I read on many sites that if I want to create a read-only property, I should use the property decorator.

Like this:

class MyClass(object):
  def __init__(self):
    self._a = None

  @property
  def a(self):
    return self._a

I think this is a good solution if I have just 1-3 read-only properties in a class. But what if I have maybe 10 of these? This would result in 40 extra lines of code only to mark all of them as read-only. In my opinion this does not really fit to Python which is meant to be a language where you do not have to write a big bunch of code to do little things.

Is there really no shorter way to make a property read-only in Python?

Upvotes: 0

Views: 258

Answers (1)

chepner
chepner

Reputation: 530960

At the very least, you could just call property as a function, rather than using it as a decorator. At the same time, you can store the underlying values in a list or dict rather than as separate attributes.

class MyClass(object):
    def __init__(self):
        self._values = [...]

    a = property(lambda self: self._values[0])
    b = property(lambda self: self._values[1])
    # etc

However, a read-only property doesn't really need to store its value in the instance dict; just hard-code the value directly in the getter:

class MyClass(object):

    a = property(lambda self: "foo")
    b = property(lambda self: "bar") 

And then wrap the call to property in another function :)

def constant(value):
    def _(self):
        return value
    return property(_)

class MyClass(object):
    a = constant("foo")
    b = constant("bar")

Here's a pure-Python read-only property, modeled after the example shown at https://docs.python.org/3/howto/descriptor.html#properties:

class Constant(object):
    def __init__(self, value)
        def _(self):
            return value
        self.fget = _

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return self.fget(obj)

This is probably simpler than subclassing property and overriding __set__ and __del__ to "unimplement" them. But, I like my idea of a wrapper around a regular property better.

Upvotes: 2

Related Questions