Ian Pilcher wrote: > I have created a class to provide a "hash consing"[1] set. > > class UniqueSet(frozenset): > > _registry = dict() > > def __new__(cls, *args, **kwargs): > set = frozenset(*args, **kwargs) > try: > return UniqueSet._registry[set] > except KeyError: > self = super(UniqueSet, cls).__new__(cls, *args, **kwargs) > UniqueSet._registry[set] = self > return self > > def __init__(self, *args, **kwargs): > pass > > I can't figure out how it works, though. In particular, I can't figure > out how the call to __new__ actually initializes the set (since my > __init__ never calls the superclass __init__). > > Is this a particular behavior of frozenset, or am I missing something > about the way that __new__ and __init__ interact?
I think __init__() is called to initialise the object after it has been created with __new__(), roughly the following, run by the metaclass: obj = UniqueSet_.__new__(UniqueSet, ...) if isinstance(obj, UniqueSet): obj.__init__(...) As Ian says, for immutable classes __init__() usually does nothing, as by definition the instance cannot be changed once created: >>> t = tuple.__new__(tuple, "ab") >>> t ('a', 'b') >>> t.__init__(None) >>> t.__init__(x=42) >>> t.__init__("whatever", "you", "like") >>> t ('a', 'b') I'm a bit surprised that the signature isn't restricted to a single positional argument... -- https://mail.python.org/mailman/listinfo/python-list