Making Python's __init__ method magical
blog.lerner.co.il
Making Python's __init__ method magical
1–10 of 42 posts
Re: Making Python's __init__ method magical
#2Re: Making Python's __init__ method magical
#3> While many people think of __init__ as a constructor, that’s not really the case. Rather, __init__ is invoked on our new object after it has been created
I'm not aware of a language (though I don't claim to know them all!) in which this is not exactly the definition of a constructor. In C++, `operator new` does the allocation, the constructor is called after. In java it's similar. In ruby it's Class#alloc (which is called by Class#new as roughly `ClassName.alloc.tap{|o| o.initialize(*args); o}`)
So the reader is correct to interpret it as a constructor. Constructors initialize the state of an uninitialized object.
Re: Making Python's __init__ method magical
#4Really really minor nitpick, but when talking about languages and their traits these little details can become important for the reader to understand, lest it confuse them about other languages: > While many people think of __init__ as a constructor, that’s not really the case. Rather, __init__ is invoked on our new object after it has been created I'm not aware of a language (though I don't claim to know them all!)…
Re: Making Python's __init__ method magical
#5 class Foo
constructor: (@x, @y) ->
@z = @x + @y
setFoo: (@foo) ->
Which compiles to: http://coffeescript.org/#try:class%20Foo%0A%20%20constructor...Re: Making Python's __init__ method magical
#6 from pprint import pprint
def default_init(init_func):
arg_count = init_func.func_code.co_argcount
arg_vars = init_func.func_code.co_varnames[1:1+arg_count]
def wrap_init(self, *args, **kwargs):
idx = 0
for arg in arg_vars:
if arg in kwargs:
setattr(self, arg, kwargs[arg])
else:
setattr(self, arg, args[idx])
idx += 1
init_func(self, *args, **kwargs)
return wrap_init
class testing(object):
@default_init
def __init__(self, a, b, c):
pass
x = testing(1, 2, 3)
pprint(x.a)
pprint(x.b)
pprint(x.c)
y = testing(1, 2, c=3)
pprint(y.a)
pprint(y.b)
pprint(y.c)
[note: I'm aware this does not do even remotely a complete job as a decorator. Use at your own risk, it is a demonstration only.]Re: Making Python's __init__ method magical
#7Really really minor nitpick, but when talking about languages and their traits these little details can become important for the reader to understand, lest it confuse them about other languages: > While many people think of __init__ as a constructor, that’s not really the case. Rather, __init__ is invoked on our new object after it has been created I'm not aware of a language (though I don't claim to know them all!)…
In Python you have a "real" constructor you can use: __new__. So I think it's good not to call __init__ a constructor. Unless of course you differ in my opinion that __new__ is a constructor?
Edited to add: Reading around, it appears that smalltalk has no separation between allocation and construction, having only the equivalent to `operator new`/`Class#new`/`obj.__new`, with initialization also happening in overloads of that. So some confusion may stem from that. I do think the distinction is meaningful and important in languages that separate these two things out, though.
Re: Making Python's __init__ method magical
#8And here's a more magical version that wraps it with a decorator. If you're gonna do this I kind of like this way better, but I'm pretty sure your average python programmer finds it obscene: from pprint import pprint def default_init(init_func): arg_count = init_func.func_code.co_argcount arg_vars = init_func.func_code.co_varnames[1:1+arg_count] def wrap_init(self, *args, **kwargs): idx = 0 for arg in arg_vars: if ar…
Re: Making Python's __init__ method magical
#9Earlier quoted context omitted.
In Python you have a "real" constructor you can use: __new__. So I think it's good not to call __init__ a constructor. Unless of course you differ in my opinion that __new__ is a constructor?
I do. __new__ is effectively an allocator, or an interface to it. It allocates an unconstructed object. Then the constructor, __init__ is called on that. Edited to add: Reading around, it appears that smalltalk has no separation between allocation and construction, having only the equivalent to `operator new`/`Class#new`/`obj.__new`, with initialization also happening in overloads of that. So some confusion may stem…
That said, I'm totally willing to believe that neither they nor I understood the difference between an "allocator" and a "constructor." I'll check into this further, both for myself and for the sake of future writing and lectures!
Re: Making Python's __init__ method magical
#10Earlier quoted context omitted.
In Python you have a "real" constructor you can use: __new__. So I think it's good not to call __init__ a constructor. Unless of course you differ in my opinion that __new__ is a constructor?
I do. __new__ is effectively an allocator, or an interface to it. It allocates an unconstructed object. Then the constructor, __init__ is called on that. Edited to add: Reading around, it appears that smalltalk has no separation between allocation and construction, having only the equivalent to `operator new`/`Class#new`/`obj.__new`, with initialization also happening in overloads of that. So some confusion may stem…