basic version of `cached_property`