I have a function that takes a string-like argument.
I want to decide if I can safely store the argument and be sure that it won't change. So I'd like to test if it's mutable, e.g the result of a buffer()
built from an array.array()
, or not.
Currently I use:
type(s) == str
Is there a better way to do it?
(copying the argument is too costly, that's why I want to avoid it)
It would be better to use
isinstance(s, basestring)
It works for Unicode strings too.
If it's just a heuristic for your caching, just use whatever works. isinstance(x, str), for example, almost exactly like now. (Given you want to decide whether to cache or not; a False-bearing test just means a cache miss, you don't do anything wrong.)
(Remark: It turns out that buffer objects are hashable, even though their string representation may change under your feet; The hash discussion below is interesting, but is not the pure solution it was intended to be.)
However, well implemented classes should have instances being hashable if they are immutable and not if they are mutable. A general test would be to hash your object and test for success.
>>> hash({})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: dict objects are unhashable
This will give false positives I'm sure, but mutable objects being hashable is strictly an interface break; I would expect python library types to obey this interface, a test of a small sample gives correct answers:
hashabe: str (Immutable), buffer (Warning, immutable slice of (possibly) mutable object!)
unhashable: list, array.array
Just use duck typing -- remember, it's "Easier to Ask for Forgiveness Than Permission". Try to mutate the string-like object, and be prepared to catch an exception if you can't.
I'd just convert it to an immutable string:
>>> s1 = "possibly mutable"
>>>
>>> s2 = str(s1)
>>> s1 is s2
True
In case s1
is immutable the same object is given back, resulting in no memory overhead. If it's mutable a copy is being made.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With