def _infer_dtype(array, name=None):
    """Given an object array with no missing values, infer its dtype from all elements."""
    if array.dtype.kind != "O":
        raise TypeError("infer_type must be called on a dtype=object array")

    if array.size == 0:
        return np.dtype(float)

    native_dtypes = set(np.vectorize(type, otypes=[object])(array.ravel()))
    if len(native_dtypes) > 1 and native_dtypes != {bytes, str}:
        raise ValueError(
            "unable to infer dtype on variable {!r}; object array "
            "contains mixed native types: {}".format(
                name, ", ".join(x.__name__ for x in native_dtypes)
            )
        )

    element = array[(0,) * array.ndim]
    # We use the base types to avoid subclasses of bytes and str (which might
    # not play nice with e.g. hdf5 datatypes), such as those from numpy
    if isinstance(element, bytes):
        return strings.create_vlen_dtype(bytes)
    elif isinstance(element, str):
        return strings.create_vlen_dtype(str)

    dtype = np.array(element).dtype
    if dtype.kind != "O":
        return dtype

    raise ValueError(
        f"unable to infer dtype on variable {name!r}; xarray "
        "cannot serialize arbitrary Python objects"
    )
Given an object array with no missing values, infer its dtype from all elements.
xarray/backends/common.py