Python descriptors which cache their output, taking into account instance attributes that they depend on