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