def getter(name, key=None):
  """
  Creates a read-only property for the attribute name *name*. If a *key*
  function is provided, it can be used to post-process the value of the
  attribute.
  """

  if not key:
    key = lambda x: x

  def wrapper(self):
    return key(getattr(self, name))
  wrapper.__name__ = wrapper.__qualname__ = name
  return property(wrapper)
Creates a read-only property for the attribute name *name*. If a *key*
  function is provided, it can be used to post-process the value of the
  attribute.