On Wed, 9 Aug 2017 10:08 am, Ian Pilcher wrote: > I have created a class to provide a "hash consing"[1] set.
Your footnote for [1] appears to be missing. What's a hash consing set? It appears to be nothing more than frozen sets which you put in a cache so as to confuse identity and value *wink* I doubt very much you're actually saving any time, since you create a temporary frozen set before returning the one in the cache. You might save some memory though. > 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__). Since frozensets are immutable, they have to be initialised in the __new__ constructor, because by the time __init__ is called the instance is immutable and cannot be updated. Your call to super() above creates a new instance. Its effectively a frozenset, except that the class of it is set to your subclass ("cls", in this case). So all the initalisation of the frozenset happens inside frozenset.__new__, which you call via super(). Your __init__ method does nothing. Get rid of it and save two lines of code :-) Also, there is at least theoretically the vague possibility that frozenset.__init__ does something (phones home to Guido?) so you shouldn't block it if you don't need to. > Is this a particular behavior of frozenset, or am I missing something > about the way that __new__ and __init__ interact? Its not just frozenset. Any mutable class must initialise its instances in __new__. Immutable classes can use either __new__ or __init__, but for historical reasons typically use __init__. The way __new__ and __init__ are called is: (1) __new__ is called; (2) if it returns an instance of cls, then instance.__init__ is called (It is not mandatory for __new__ to return a new instance of its class; it can return whatever you like. That is a feature, and there are occasional uses for it.) -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list