title: Passing helper variables to dataclass __init__ without assigning them
body: <p>I have a root-level <code>config</code> class that I pass throughout my codebase through dependency injection.</p>
  
  <p>Problem is, I have this dataclass that needs some attributes from this config to calculate a value <code>world_coords</code> in <code>__post_init__()</code>.</p>
  
  <p>In order to keep my tests clean and to circumvent other test import issues (not discussed here), I want to be able to pass in the config directly to this object instead of reading these values from an import. If I structure the config as an argument, however, it becomes an attribute of the dataclass, which I'm trying to avoid. There isn't really a need for <code>RoadSegmentNode</code> to hold on to a reference of the config once used.</p>
  
  <p>Here's the basic structure of the class:</p>
  
  <pre><code>@dataclass(eq=True, frozen=True)  # make hashable
  class RoadSegmentNode:
  
      tile_index: Tuple[int, int]  # (r, c)
      dir: Direction
      node_type: RoadNodeType
      world_coords: Tuple[int, int] = field(init=False)
  
      def __post_init__(self):
  
          # (Use config variables here, e.g. `config.TILE_WIDTH`, to calculate x and y)
  
          # Hack to get around frozen=True. We don't care that we're mutating
          # an "immutable" object on __init__().
          object.__setattr__(self, "world_coords", (x, y))
  </code></pre>
  
  <p>Here's the stopgap I went with to keep with the dependency injection model to unblock my tests for now. Note how <code>RoadSegmentNode</code> now has a bunch of new attributes that would only use for initialization. It's a little better than keeping a reference to the config, because at least they're explicit, but it's still a pretty poor design.</p>
  
  <pre><code>@dataclass(eq=True, frozen=True)  # make hashable
  class RoadSegmentNode:
  
      # NOTE: DO NOT ACCESS THESE ATTRIBUTES!
      grid_width: int
      grid_height: int
      tile_width: int
      tile_height: int
      road_width: int
  
      tile_index: Tuple[int, int]  # (r, c)
      dir: Direction
      node_type: RoadNodeType
      world_coords: Tuple[int, int] = field(init=False)
  
      def __post_init__(self):
  
          # (Use attributes here, e.g. `self.tile_width`, to calculate x and y)
  
          # Hack to get around frozen=True. We don't care that we're mutating
          # an "immutable" object on __init__().
          object.__setattr__(self, "world_coords", (x, y))
  </code></pre>
  
  <p>How can I pass the config to the dataclass for initialization without making it an attribute of the dataclass? Should I even be considering a dataclass for this use case? I believe the original intention was to keep all instances immutable, but I can't confirm.</p>