'Checks if the given Attribute (or list of Attributes) exists on
the object.
Args:
key (str or iterable): The Attribute key or keys to check for.
If `None`, search by category.
category (str or None): Limit the check to Attributes with this
category (note, that `None` is the default category).
Returns:
has_attribute (bool or list): If the Attribute exists on
this object or not. If `key` was given as an iterable then
the return is a list of booleans.'

def has(self, key=None, category=None):

    ret = []
    for keystr in make_iter(key):
        ret.extend((bool(attr) for attr in self._getcache(keystr, category)))
    return (ret[0] if (len(ret) == 1) else ret)
