> Even `Path("config.json").read_text()` in a constructor isn't a good idea.
If that call is necessary to ensure that the instance has a good/known internal state, I absolutely think it belongs in __init__ (whether called directly or indirectly via a method).
You're right that consistent internal state is important, but you can accomplish this with
class MyClass:
def __init__(self, config: str):
self._config = config
And if your reaction is "that just means something else needs to call Path("config.json").read_text()", you're absolutely right! It's separation of concerns; let some other method deal with the possibility that `config.json` isn't accessible. In the real world, you'd presumably want even more specific checks that specific config values were present in the JSON file, and your constructor would look more like
def __init__(self, host: str, port: int):
and you'd validate that those values are present in the same place that loads the JSON.
This simple change makes code so much more readable and testable.
If that call is necessary to ensure that the instance has a good/known internal state, I absolutely think it belongs in __init__ (whether called directly or indirectly via a method).