The right way to 'call' a class attribute inside the same class

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Dec 13 00:36:31 EST 2016


On Tuesday 13 December 2016 12:12, Ned Batchelder wrote:

> On Monday, December 12, 2016 at 6:17:43 PM UTC-5, Ben Finney wrote:
>> Ned Batchelder <ned at nedbatchelder.com> writes:
>> 
>> > Claiming that __init__ isn't a constructor seems overly pedantic to
>> > me.
>> 
>> Whereas to me, claiming that ‘Foo.__init__’ is a constructor seems
>> needlessly confusing.
>> 
> ...
>> * A constructor should return the instance. ‘Foo.__init__’ does not do
>>   that; ‘Foo.__new__’ does.
> 
> This seems like an odd thing to insist on. C++ and Java constructors
> don't return the instance.

I'm not sure what you mean by that. I think they do, at least in C++.

Normally in C++ you would create an instance like this:

MyClass obj(arg);


In Python terms, that would be written as: `obj = MyClass(arg)`.


But one can also create "anonymous objects" which aren't assigned to a named 
variable:

something.method( MyClass(args) );


Doesn't that count as "returning an instance"?


> C++ allocators return the instance.

As I understand it, C++ allocators are specialist methods used in the standard 
library for container classes which allocate storage, i.e. the equivalent of 
Python lists and dicts.

http://en.cppreference.com/w/cpp/concept/Allocator

As far as I can tell, they aren't relevant to "simple" record- or struct-like 
objects.


> I'm happy to call __new__ an allocator. It serves exactly the same
> role in Python as allocators do in C++: its job is to create the raw
> material for the object, and they very rarely need to be written.

I think that last part is wrong in Python. Any time you are creating an 
immutable class -- and some of us do that a lot -- you generally need to write 
__new__. That makes __new__ very different from C++ allocators, and more like 
C++ constructors.

On the other hand, __new__ seems to be quite similar to ObjectiveC's `alloc`, 
which is called the allocator, and __init__ similar to ObjectiveC's init, which 
is the initialiser!

ObjectiveC also has a new method, which just calls alloc then init.


>> 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.
> 
> Creating objects is confusing, but beginners don't come to Python
> with an expectation of what a "constructor" is.  Filling in the
> attributes of an object is just as clearly a kind of construction
> as allocating memory.


Remember that in Python __new__ can do a lot more than just allocate memory.

It just seems really weird to describe __init__ as a constructor when it 
initialises an existing instance: "initialiser" just seems to be the obvious 
term for it. (Do I really need to spell it out? __INIT__/INITialiser.)

Python's object creation model seems to be a lot closer to that of ObjectiveC 
or C++ than Javascript, so copying Javascript's terminology seems risky to me.



-- 
Steven
"Ever since I learned about confirmation bias, I've been seeing 
it everywhere." - Jon Ronson



More information about the Python-list mailing list