Milano
Milano

Reputation: 18745

Python's method like 'equals' in Java

How could I make set to have objects equality depended on a custom attribute which I'd set? Like Java's equals method.

The point is that I want to have a set which contains tuples (x,y). When I try to put (x,y) tuple into the set, the result would depends on x.

set.add((x,y))
- OK 
set.add((x,z))
- Can't add because there is already a touple which has x as a first value. 

Upvotes: 2

Views: 703

Answers (1)

Mahi
Mahi

Reputation: 21942

Why not use a dict instead of a set of tuples:

d = {}
d[x] = y
d[x] = z

This will override the value y with z though, but it makes sure you only have one value at a time.

If you don't want the overriding to be possible, you can subclass dict to prevent it:

class HalfFrozenDict(dict):  # Name is a subject to change

    def __setitem__(self, key, value):
        if key in self:
            raise KeyError("Key '{}' already exists!".format(key))
        super().__setitem__(key, value)

    def update(self, other):
        other = {key: other[key] for key in other if key not in self}
        super().update(other)

Currently it raises an error if you try to re-set an item:

>>> d = HalfFrozenDict()
>>> d[0] = 1
>>> d[0] = 2
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    d[0] = 2
  File "<pyshell#1>", line 5, in __setitem__
    raise KeyError("Key: '{}' already exists!".format(key))
KeyError: "Key '0' already exists!"

Also, calling d.update(other) will just ignore the duplicate keys from the other dict.

Both of these behaviours are a subject to change: would you rather raise an error on "invalid" update() call? Would you prefer to ignore a re-setting of an item (I think error is better in this case)?

Upvotes: 2

Related Questions