code: def union_join(left, right, left_as='left', right_as='right'):
      
      attrs = {}
      attrs.update(get_object_attrs(right))
      attrs.update(get_object_attrs(left))
      attrs[left_as] = left
      attrs[right_as] = right
      if isinstance(left, dict) and isinstance(right, dict):
          return attrs
      else:
          joined_class = type(left.__class__.__name__ + right.__class__.__name__, (Union,),
                              {})
          return joined_class(attrs)
docs: Join function truest to the SQL style join.  Merges both objects together in a sum-type,
      saving references to each parent in ``left`` and ``right`` attributes.
  
          >>> Dog = namedtuple('Dog', ['name', 'woof', 'weight'])
          >>> dog = Dog('gatsby', 'Ruff!', 15)
          >>> Cat = namedtuple('Cat', ['name', 'meow', 'weight'])
          >>> cat = Cat('pleo', 'roooowwwr', 12)
          >>> catdog = union_join(cat, dog, 'cat', 'dog')
          >>> catdog.name
          pleo
          >>> catdog.woof
          Ruff!
          >>> catdog.dog.name
          gatsby
  
      :param left: left object to be joined with right
      :param right: right object to be joined with left
      :return: joined object with attrs/methods from both parents available