I'm trying to the understand the initialization function in a python class system implementation, taken from this book (SICP python - reference to book section).
The init_instance
(initialization) function """Return a new object with type cls, initialized with args."""
is where I'm having trouble. Below I've tried to narrow down my question, by explaining what I've understood.
def make_instance (cls): #good with this
"""return a new object instance, which is a dispatch dictionary"""
def get_value(name):
if name in attributes:
return attributes[name]
else:
value = cls ['get'](name)
return bind_method (value, instance)
def set_value (name, value):
attributes [name] = value
attributes = {}
instance = {'get': get_value, 'set': set_value}
return instance
def bind_method (value, instance): #good with this
"""Return a bound method if value is callable, or value otherwise"""
if callable (value):
def method(*args):
return value (instance, *args)
return method
else:
return value
def make_class (attributes, base_class = None):
"""Return a new class, which is a dispatch dictionary."""
def get_value(name):
if name in attributes:
return attributes[name]
elif base_class is not None:
return base_class['get'](name)
def set_value(name,value):
attributes[name] = value
def new(*args):
return init_instance(cls, *args)
cls = {'get':get_value,'set':set_value,'new':new}
return cls
def init_instance(cls,*args): #problem here
"""Return a new object with type cls, initialized with args"""
instance = make_instance (cls)
init = cls ['get'] ('__init__')
if init:
init (instance, *args) #No return function here
return instance
Here is a call to above functions, to create a new class object called 'Jim'
def make_my_class(): #define a custom class
pass
return make_class({'__init__':__init__}) #return function that implements class
my_class = make_my_class() #create a class
my_class_instance = my_class['new'] ('Jim') #create a class instance with ['new']
What I understand
Since this is an functional implementation of classes, the comparison is with inbuilt python classes. Below wherever I say Python Class/object/instance, I mean inbuilt.
make_instande(cls)
: takes the 'class' ->cls
argument (a message fxn dictionary itself) and describes the behaviour of an object , i.e. provides required properties to behave in a similar way to a python object. We can set attributes, that stay local to attributes dictionary using 'set
'. Usingget
, if the attribute is not in object, it is looked up in class definition and abind_method
function is called.bind_method(value,instance)
: binds a function in class definition to the object instance to emulate python methods in a python class instance. if value is not callable, returns value (python attribute from parent class).make_class (attributes, base_class = None)
: Sets the behaviour of a class, with ability to inherit from another class. Uses get and set to in a similar fashion to make_instance, except, it doesn't require a bind_method. It usesinit_instance(cls, *args)
to create a new object instance with arbitrary number of arguments (for methods of the attributes).cls
argument forinit_instance
passes class dispatch dictionary to the object instance. Hence, the object 'inherits' (for lack of a better word) the class features.init_instance(cls, *args)
: Here I am a little unsure. Firstly, the function makes an instance withinstance = make_instance(cls)
, the instance inherits features of the class throughcls
dictionary.init = cls['get']('__init__')
,init
is created, a statement that looks up if__init__
keyword was passed in attributes tomake_class
, ,if init: init(instance, *args)
makes args local to the instance? Returns an instance.
I can narrow down my question to -
init_instance
is a return to new(*args)
in make_class
. Which means an instance dictionary is returned to new(*args)
. However, make_class
returns cls
which means we have to update cls
somehow to contain instance
properties. How is that that being done? It's most likely this statement init (instance, *args)
but I don't know how to break down this statement. I haven't seen init
as fn, how are arguments being passed to it?
This code is a little tricky, so it's not surprising that you find some of it puzzling. To understand it, you need to understand closures. There's some info about closures in Python in this answer.
init_instance
creates a new instance withinstance = make_instance(cls)
, then it looks up theinit
method ofcls
, and if it exists, it calls thatinit
method with the new instance and whatever was passed inargs
. Neithermake_instance
norinit_instance
modify thecls
dictionary, or theattributes
dictionary that was passed tomake_class
whencls
was created. What actually happens is that each call ofmake_instance
creates a newattributes
dict for the instance it creates, which theget
andset
functions in the instance dict can reference.Your
make_my_class
definition doesn't make much sense. It has a redundantpass
statement, andmake_class({'__init__': __init__})
won't work because you haven't defined__init__
anywhere, that needs to be a function which will initialize your class instances.Here's a modified version of your code. I've created a simple
__init__
function formy_class
, and added severalprint
calls so we can get an idea of what the code's doing.output