0

I've got a somewhat complex data-type Mask that I'd like to be able to use fast identity checking for such as:

seen = set()
m = Mask(...)
if m in seen:
    ...

This suggests that Mask should be hashable and therefore immutable. However, I'd like to generate variants of m and Mask seems like the place to encapsulate the variation logic. Here is a minimalish example that demonstrates what I want to accomplish:

class Mask(object):
    def __init__(self, seq):
        self.seq = seq
        self.hash = reduce(lambda x, y: x ^ y, self.seq)

    # __hash__ and __cmp__ satisfy the hashable contract §3.4.1)
    def __hash__(self):
        return self.hash

    def __cmp__(self, other):
        return cmp(self.seq, other.seq)

    def complement(self):
        # cannot modify self without violating immutability requirement
        # so return a new instance instead
        return Mask([-x for x in self.seq])

This satisfies all of the hashable and immutable properties. The peculiarity is having what is effectively a Factory method complement; is this a reasonable way to implement the desired function? Note that I am not at all interested in protecting against "malicious" modification as many related questions on SO are looking to achieve.

As this example is intentionally small it could be trivially solved by making a tuple of seq. The type that I am actually working with does not afford such simple casting.

4

3 回答 3

2

Yes, this is pretty much how you write an immutable class; methods that would otherwise change an object's state become, in your terms, "factories" that create new instances.

Note that in the specific case of computing a complement, you can name the method __invert__ and use it as

inv_mask = ~mask

Operator syntax is a strong signal to client code that operations return new values of the same type.

于 2012-06-01T14:15:41.617 回答
1

When using immutable types, all 'variation' methods must return new objects/instances, and thus be factories in that sense.

Many languages make strings immutable (including Python). So all string operations return new strings; strB = strA.replace(...) etc.

If you could change the instance at all, it wouldn't be immutable.

Edit:

Rereading, you're asking if this is reasonable, and I say yes. The logic would not be better put somewhere else, and as I pointed out with string immutability it is a common paradigm to get new variations from existing ones.

于 2012-06-01T14:07:51.113 回答
1

Python doesn't inforce immutability. It is up to you to make sure that objects are not modified while they are in a set. Otherwise you don't need immutability to use sets, dictionaries in Python.

于 2012-06-01T14:29:02.990 回答