我正在尝试理解python类系统实现中的初始化函数,取自本书(SICP python - reference to book section)。
init_instance
(初始化)函数"""Return a new object with type cls, initialized with args."""
是我遇到麻烦的地方。下面我试图通过解释我所理解的内容来缩小我的问题。
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
这是对上述函数的调用,用于创建一个名为'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']
由于这是类的功能实现,因此与内置的python类进行比较。无论我在哪里说Python Class / object / instance,我的意思是内置。
make_instande(cls)
:接受'class' - > cls
参数(消息fxn字典本身)并描述对象的行为,即提供与python对象类似的行为所需的属性。我们可以使用“set
”设置属性,这些属性保留在属性字典的本地。使用get
,如果属性不在对象中,则在类定义中查找它,并调用bind_method
函数。 bind_method(value,instance)
:将类定义中的函数绑定到对象实例,以模拟python类实例中的python方法。如果value不可调用,则返回value(父类的python属性)。 make_class (attributes, base_class = None)
:设置一个类的行为,具有从另一个类继承的能力。使用get和set以与make_instance类似的方式,除了它不需要bind_method。它使用init_instance(cls, *args)
创建具有任意数量参数的新对象实例(对于属性的方法)。 cls
的{{1}}参数将类调度字典传递给对象实例。因此,对象'继承'(缺乏更好的词)的类特征。 init_instance
:我有点不确定。首先,该函数使用init_instance(cls, *args)
创建一个实例,该实例通过instance = make_instance(cls)
字典继承该类的功能。 cls
创建了init = cls['get']('__init__')
,这是一个查找init
关键字是否已在属性中传递给__init__
的语句,make_class
使得args在实例的本地?返回一个实例。 if init: init(instance, *args)
返回init_instance
中的new(*args)
。这意味着实例字典将返回make_class
。但是,new(*args)
会返回make_class
,这意味着我们必须以某种方式更新cls
以包含cls
属性。那怎么样?这很可能就是instance
,但我不知道如何打破这种说法。我没有看到init (instance, *args)
为fn,如何将参数传递给它?
答案 0 :(得分:1)
这段代码有点棘手,所以你发现它的一些令人费解并不奇怪。要理解它,您需要了解closures。在this answer中有关于Python中闭包的一些信息。
init_instance
使用instance = make_instance(cls)
创建新实例,然后查找init
的{{1}}方法,如果它存在,则会调用cls
使用新实例的方法以及init
中传递的任何内容。 args
和make_instance
都不会修改init_instance
字典,也不会修改cls
创建attributes
时传递给make_class
的字典。实际发生的是每次调用cls
都会为它创建的实例创建一个新的make_instance
dict,实例dict中的attributes
和get
函数可以引用它。
您的set
定义没有多大意义。它有一个冗余的make_my_class
语句,并且pass
无法正常工作,因为您还没有在任何地方定义make_class({'__init__': __init__})
,这需要是一个初始化类实例的函数
这是您的代码的修改版本。我为__init__
创建了一个简单的__init__
函数,并添加了几个my_class
调用,以便我们了解代码的作用。
print
<强>输出强>
def hexid(obj):
return hex(id(obj))
def make_instance(cls): # good with this
""" Return a new object instance, which is a dispatch dictionary """
def get_value(name):
print('INSTANCE GET_VALUE', name, 'from', hexid(attributes))
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 = {'test': 'Default Test'}
print('Created instance attributes', hexid(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):
print('\nCLASS GET_VALUE', name, 'from', hexid(attributes))
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)
print('Creating class with attributes', hexid(attributes))
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:
print('Calling init of', hexid(cls), 'on', hexid(instance), 'with', args)
init(instance, *args) #No return here
return instance
def make_my_class(): # define a custom class
# Create a simple __init__ for the class
def __init__(inst, *args):
print('INIT', hexid(inst), args)
inst['set']('data', args)
# return a dict that implements class
return make_class({'__init__': __init__})
# test
#create a class
my_class = make_my_class()
#create some class instances
jim = my_class['new']('Jim')
jim['set']('test', 'Hello')
fred = my_class['new']('Fred')
print('CLASS', hexid(my_class))
print('\nINSTANCE', hexid(jim))
print(jim['get']('data'))
print(jim['get']('test'))
print('\nINSTANCE', hexid(fred))
print(fred['get']('data'))
print(fred['get']('test'))