The right way to 'call' a class attribute inside the same class
steve+comp.lang.python at pearwood.info
Tue Dec 13 00:45:41 EST 2016
On Tuesday 13 December 2016 10:23, Chris Angelico wrote:
> On Tue, Dec 13, 2016 at 10:17 AM, Ben Finney <ben+python at benfinney.id.au>
>> If the differences didn't matter I would agree that “overly pedantic” is
>> fair. But those differences trip up newcomers. Thinking of
>> ‘Foo.__init__’ leads people to wonder where the ‘self’ attribute came
>> from – am I not meant to be constructing it? — and to attempt to return
>> that instance. And when the time comes to lean about ‘__new__’ the
>> confusion continues, because the newcomer has been told that something
>> *else* is the constructor, so what's this?
> constructor". When you do, there is a 'this' object before you start.
> 'this' should end up existing?
You've ignored Ben's critical point that if we call __init__ the "constructor",
what do we call __new__? (Perhaps we should call __new__ the "initialiser" for
that we shouldn't feel the need to mindlessly copy C++ terminology. Is it your
C++ or ObjectiveC? Even when it goes against the obvious English mnemonic?
__init__ is the INITialiser (it initialises an existing instance);
__new__ creates/constructs a NEW instance
> Does it really even matter when memory
> gets allocated and the object's identity assigned?
Actually, yes it does. Try constructing an immutable object like a subclass of
float, str or int from the __init__ method. Attaching attributes to the
instance doesn't count.
def __init__(self, arg):
arg = abs(arg)
return super().__init__(self, arg)
So much fail...
> Before __init__
> gets called, the object isn't "truly there" - its fundamental
> invariants may not yet have been established, and key attributes might
> not have been set up.
"Fundamental invariants" is tricky though -- are they *truly* fundamental? This
is Python -- I can easily make a Python-based class that lacks the attributes
that its methods assume will be there, or delete them after creation.
But there is one thing which truly is fundamental: the instance creation, the
moment that object.__new__ returns a new instance. Before calling that, the
instance genuinely doesn't exist; after object.__new__ returns, it genuinely
does. (Even if it isn't fully initialised.)
Unlike __init__, object.__new__ is atomic: it either succeeds, or it doesn't.
So object.__new__ really is the constructor of instances, and so following
standard practice, MyClass.__new__ which inherits from object ought to be
called the same thing. (Even if it is no longer atomic, due to being written in
> Once __init__ finishes, there is an expectation
> that attributes and invariants are sorted out.
> This is like the old "Python doesn't have variables" thing.
> Ultimately, every language has slightly different semantics (otherwise
> they'd be trivial transformations, like Ook and Brainf*), so you have
> to learn that the "constructor" might have slightly different
> semantics. Accept it - embrace it. Learn it.
We're not debating what other languages should call __new__ and __init__ or
whatever their equivalents are. We're debating what Python should call them.
For some prior art, consider ObjectiveC. To create a new instance of a class,
[[MyClass alloc] init]
where alloc is the "allocator" (it basically just allocates memory, and very
little else) and init is the "initialiser" (because it initialises the newly
In more modern versions of ObjectiveC, there's a short-cut:
where new calls alloc then init for you.
In Ruby, people think of two distinct things as the "constructor", depending on
what you are doing. [Source: my resident Ruby expert at work.] If you are
talking about *writing* a class, the constructor is the initialize method:
But if you are talking about *creating an instance* it is the new method:
which itself automatically calls initialize behind the scenes. (I'm told that
it is possible to override new, but nobody does it.)
It seems to me that both of these are quite similar to Python's model.
"Ever since I learned about confirmation bias, I've been seeing
it everywhere." - Jon Ronson
More information about the Python-list