How to tell if a sequence is mutable or not?

There is no simple solution until there is no understanding of what you are trying to achieve, so we need to understand what mutability is?

Let's simply define mutable type as type for which instances we can set item in some position (by key in dictionaries, by index in lists), i. e. they implement __setitem__ method.

Most preferred way of checking something in Python is to ask forgiveness, not permission, so something like this will help

def is_mutable(cls):
    try:
        cls.__setitem__
    except AttributeError:
        return False
    else:
        return True

but it also can be replaced with

def is_mutable(cls):
    return hasattr(cls, '__setitem__')

both work similar, depends on your taste.

Example

types = [tuple, str, list, dict]
for type_ in types:
    print(type_.__name__, 'is mutable:', is_mutable(type_))

gives us

tuple is mutable: False
str is mutable: False
list is mutable: True
dict is mutable: True

You can check whether the type is a subclass of the collections.abc.MutableSequence abstract base class (or collections.MutableSequence in Python 2):

>>> issubclass(list, MutableSequence)
True
>>> issubclass(tuple, MutableSequence)
False

>>> isinstance([], MutableSequence)
True
>>> isinstance((), MutableSequence)
False

Note that unlike some ABCs (e.g., Collection and Iterable, which provide hooks for issubclass/isinstance) this one requires its subclasses to be explicitly registered, so this may not work out-of-the-box with all sequence-ish types.

However, you can manually register a type as a subclass using MutableSequence.register(MyType), as long as the required abstract methods are implemented.

Tags:

Python