<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def offset(polygons, distance, join='miter', tolerance=2, precision=0.001, join_first=False, max_points=199, layer=0, datatype=0):
 """ Shrink or expand a polygon or polygon set. Parameters polygons : polygon or array-like Polygons to be offset. Must be a ``PolygonSet``, ``CellReference``, ``CellArray``, or an array. The array may contain any of the previous objects or an array-like[N][2] of vertices of a polygon. distance : number Offset distance. Positive to expand, negative to shrink. join : {'miter', 'bevel', 'round'} Type of join used to create the offset polygon. tolerance : number For miter joints, this number must be at least 2 and it represents the maximun distance in multiples of offset betwen new vertices and their original position before beveling to avoid spikes at acute joints. For round joints, it indicates the curvature resolution in number of points per full circle. precision : float Desired precision for rounding vertice coordinates. join_first : bool Join all paths before offseting to avoid unecessary joins in adjacent polygon sides. max_points : integer If greater than 4, fracture the resulting polygons to ensure they have at most ``max_points`` vertices. This is not a tessellating function, so this number should be as high as possible. For example, it should be set to 199 for polygons being drawn in GDSII files. layer : integer The GDSII layer number for the resulting element. datatype : integer The GDSII datatype for the resulting element (between 0 and 255). Returns ------- out : ``PolygonSet`` or ``None`` Return the offset shape as a set of polygons. """

    poly = []
    if isinstance(polygons, PolygonSet):
        poly.extend(polygons.polygons)
    elif isinstance(polygons, CellReference) or isinstance(
            polygons, CellArray):
        poly.extend(polygons.get_polygons())
    else:
        for obj in polygons:
            if isinstance(obj, PolygonSet):
                poly.extend(obj.polygons)
            elif isinstance(obj, CellReference) or isinstance(obj, CellArray):
                poly.extend(obj.get_polygons())
            else:
                poly.append(obj)
    result = clipper.offset(poly, distance, join, tolerance, 1 / precision, 1
                            if join_first else 0)
    return None if len(result) == 0 else PolygonSet(
        result, layer, datatype, verbose=False).fracture(
            max_points, precision)