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.