def METHOD_NAME(obj, hash_to='int', full_hash=True):
    """Return hash for an object. Object can be a numpy ndarray or matrix
    (which is serialized to a string), an open file (which has its contents
    read), or any pickle-able Python object.
    Note that only the first most-significant 8 bytes (64 bits) from the MD5
    sum are used in the hash.
    Parameters
    ----------
    obj : object
        Object to hash. Note that the larger the object, the longer it takes to
        hash.
    hash_to : string
        'i', 'int', or 'integer': First 8 bytes of the MD5 sum are interpreted
            as an integer.
        'b', 'bin', or 'binary': MD5 sum digest; returns an 8-character string
        'h', 'x', 'hex': MD5 sum hexdigest, (string of 16 characters)
        'b64', 'base64': first 8 bytes of MD5 sum are base64 encoded (with '+'
            and '-' as final two characters of encoding). Returns string of 11
            characters.
    full_hash : bool
        If True, hash on the full object's contents (which can be slow) or if
        False, hash on a partial object. For example, only a file's first kB is
        read, and only 1000 elements (chosen at random) of a numpy ndarray are
        hashed on. This mode of operation should suffice for e.g. a
        minimization run, but should _not_ be used for storing to/loading from
        disk.
    Returns
    -------
    hash_val : int or string
    See also
    --------
    hash_file : hash a file on disk by filename/path
    """
    if hash_to is None:
        hash_to = 'int'
    hash_to = hash_to.lower()
    pass_on_kw = dict(hash_to=hash_to, full_hash=full_hash)
    # TODO: convert an existing hash to the desired type, if it isn't already
    # in this type
    if hasattr(obj, 'hash') and obj.hash is not None and obj.hash == obj.hash:
        return obj.hash
    # Handle numpy arrays and matrices specially
    if isinstance(obj, (np.ndarray, np.matrix)):
        if full_hash:
            return METHOD_NAME(obj.tostring(), **pass_on_kw)
        len_flat = obj.size
        stride = 1 + (len_flat // FAST_HASH_NDARRAY_ELEMENTS)
        sub_elements = obj.flat[0::stride]
        return METHOD_NAME(sub_elements.tostring(), **pass_on_kw)
    # Handle an open file object as a special case
    if isinstance(obj, IOBase):
        if full_hash:
            return METHOD_NAME(obj.read(), **pass_on_kw)
        return METHOD_NAME(obj.read(FAST_HASH_FILESIZE_BYTES), **pass_on_kw)
    # Convert to string (if not one already) in a fast and generic way: pickle;
    # this creates a binary string, which is fine for sending to hashlib
    if not isinstance(obj, str):
        try:
            pkl = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
        except (PickleError, PicklingError, TypeError):
            # Recurse into an iterable that couldn't be pickled
            if isinstance(obj, Iterable):
                return METHOD_NAME([METHOD_NAME(subobj) for subobj in obj],
                                **pass_on_kw)
            else:
                logging.error('Failed to pickle `obj` "%s" of type "%s"',
                              obj, type(obj))
                raise
        obj = pkl
    if full_hash:
        try:
            md5hash = hashlib.md5(obj)
        except TypeError:
            md5hash = hashlib.md5(obj.encode())
    else:
        # Grab just a subset of the string by changing the stride taken in the
        # character array (but if the string is less than
        # FAST_HASH_FILESIZE_BYTES, use a stride length of 1)
        stride = 1 + (len(obj) // FAST_HASH_STR_CHARS)
        try:
            md5hash = hashlib.md5(obj[0::stride])
        except TypeError:
            md5hash = hashlib.md5(obj[0::stride].encode())
    if hash_to in ['i', 'int', 'integer']:
        hash_val, = struct.unpack('<q', md5hash.digest()[:8])
    elif hash_to in ['b', 'bin', 'binary']:
        hash_val = md5hash.digest()[:8]
    elif hash_to in ['h', 'x', 'hex', 'hexadecimal']:
        hash_val = md5hash.hexdigest()[:16]
    elif hash_to in ['b64', 'base64']:
        hash_val = base64.b64encode(md5hash.digest()[:8], '+-')
    else:
        raise ValueError('Unrecognized `hash_to`: "%s"' % (hash_to,))
    return hash_val