views:

45

answers:

1

I've the following class:

class MySet(set):

    def __init__(self, arg=None):
        if isinstance(arg, basestring):
            arg = arg.split()
        set.__init__(self, arg)

This works as expected (initialising the set with the words of the string rather than the letters). However when I want to do the same with the immutable version of set, the __init__ method seems to be ignored:

class MySet(frozenset):

    def __init__(self, arg=None):
        if isinstance(arg, basestring):
            arg = arg.split()
        frozenset.__init__(self, arg)

Can I achieve something similar with __new__ ?

+4  A: 

Yes, you need to override __new__ special method:

class MySet(frozenset):

    def __new__(cls, *args):
        if args and isinstance (args[0], basestring):
            args = (args[0].split (),) + args[1:]
        return super (MySet, cls).__new__(cls, *args)

print MySet ('foo bar baz')

And the output is:

MySet(['baz', 'foo', 'bar'])
doublep
super! can __init__ be deprecated?
EoghanM
@EoghanM: No, `__new__` is different. Basically, `__new__` creates *or* lookups an instance, while `__init__` setups an already created instance. Main reasons to override `__new__` is to avoid new instance creation (e.g. to make `SomeType ()` always return the same singleton object), or to subclass certain immutable types, like `frozenset`. See http://docs.python.org/reference/datamodel.html#special-method-names for details.
doublep
@doublep thx - my sub question posed more clearly here: http://stackoverflow.com/questions/3131488/
EoghanM