__new__

Rhamphoryncus rhamph at gmail.com
Mon Aug 4 17:12:19 EDT 2008


On Aug 4, 11:46 am, Ethan Furman <et... at stoneleaf.us> wrote:
> Mel wrote:
> > Ethan Furman wrote:
>
> >>Emile van Sebille wrote:
>
> >>>Ethan Furman wrote:
>
> >>>>    --> d25._int = (1, 5)
>
> >>>Python considers names that start with a leading underscore as internal
> >>>or private, and that abuse is the burden of the abuser...
> >>>Is bytecodehacks still around?  That was serious abuse  :)
>
> >>Good point.  What I'm curious about, though, is the comment in the code
> >>about making the Decimal instance immutable.  I was unable to find docs
> >>on that issue.
>
> > There's something in the Language Reference, chapter 3.1 'Objects, Values
> > and Types'.
>
> >         Mel.
>
> Thanks, Mel.
>
> I had actually read that once already, but your post caused me to reread
> it, and evidently the ideas there had had enough time to percolate
> through my mind.
>
> --> from decimal import Decimal
> --> d25 = Decimal(25)
> --> d25
> Decimal("25")
> --> d25.testing = 'immutable'
> Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
> AttributeError: 'Decimal' object has no attribute 'testing'
>
> Decimals are immutable in that we cannot add new attributes to them.
>
> The documentation in Language Reference 3.4.2.4 '__slots__' has this to say:
>         If defined in a new-style class, __slots__ reserves space for
>         the declared variables and prevents the automatic creation of
>         __dict__ and __weakref__ for each instance.
> and
>         Without a __dict__ variable, instances cannot be assigned new
>         variables not listed in the __slots__ definition. Attempts to
>         assign to an unlisted variable name raises AttributeError.
>
> So the question I have now is this:  is __new__ necessary, or would
> __init__ have also worked?  Let's see...
>
> class tester(object):
>      __slots__ = ['test1', 'test2', 'test3']
>      def __init__(self, value1, value2, value3):
>          self.test1 = value1
>          self.test2 = value2
>          self.test3 = value3
>
> --> import tester
> --> testee = tester.tester(1, 2, 3)
> --> testee
> <tester.tester object at 0x009E7328>
> --> dir(testee)
> ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
>   '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
>   '__repr__', '__setattr__', '__slots__', '__str__', 'test1', 'test2',
>   'test3']
> --> testee.test4 = 4
> Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
> AttributeError: 'tester' object has no attribute 'test4'
>
> For this simple test, it looks like __init__ works just fine.  So,
> besides consistency (which is important) am I missing any other reasons
> to use __new__ instead of __init__?

If you subclass a builtin immutable like int then you need to override
__new__, as __init__ has no effect.  Decimal is written in python, so
this is irrelevant, but if there are plans to rewrite it in C (which I
believe there are) then it'd need to use __new__ at that point.  Using
__new__ even in the python version then becomes a way to future-proof
the API.



More information about the Python-list mailing list