代码之家  ›  专栏  ›  技术社区  ›  pyeR_biz

类实例实现,初始化实例-来自sicp python

  •  2
  • pyeR_biz  · 技术社区  · 6 年前

    我试图理解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类/对象/实例是指内置的。

    • make_instande(cls) :获取“类”-> cls 参数(消息fxn字典本身)并描述对象的行为,即提供必需的属性以类似于python对象的方式进行操作。我们可以设置属性,使用属性字典保持本地属性。 set '.使用 get ,如果属性不在对象中,则在类定义和 bind_method 函数被调用。
    • bind_method(value,instance) :将类定义中的函数绑定到对象实例,以模拟python类实例中的python方法。如果value不可调用,则返回value(来自父类的python属性)。
    • make_class (attributes, base_class = None) :设置类的行为,具有从另一个类继承的能力。以类似的方式使用get和set to来创建_实例,但不需要bind_方法。它使用 init_instance(cls, *args) 创建具有任意数量参数的新对象实例(用于属性的方法)。 CLS 论证 初始化实例 将类调度字典传递给对象实例。因此,对象“继承”(因为缺少更好的词)类特性。
    • 初始化实例(cls,*args) :我有点不确定。首先,函数使用 instance = make_instance(cls) ,实例通过 CLS 字典。 init = cls['get']('__init__') , init 是一个语句,它查找 __init__ 关键字在属性中传递给 make_class ,, if init: init(instance, *args) 使args成为实例的本地参数?返回实例。

    我可以把问题缩小到

    初始化实例 是一种回归 new(*args) 在里面 MaMax类 . 这意味着实例字典返回给 新(*ARG) . 然而, MaMax类 收益率 CLS 这意味着我们必须更新 CLS 以某种方式控制 instance 性质。怎么做到的?很可能是这个声明 init (instance, *args) 但我不知道如何打破这个说法。我没见过 初始化 作为fn,如何将参数传递给它?

    1 回复  |  直到 6 年前
        1
  •  1
  •   PM 2Ring    6 年前

    这段代码有点棘手,所以您会发现其中一些问题并不奇怪。要理解它,你需要理解 closures . 在python中有一些关于闭包的信息 this answer .

    init_instance 使用创建新实例 instance = make_instance(cls) ,然后它查找 init 方法 cls ,如果它存在,它称之为 初始化 方法与新实例以及所传递的任何内容 args . 既不 make_instance 也不 初始化实例 修改 CLS 字典,或 attributes 字典被传递给 make_class 什么时候 CLS 被创造。实际发生的是 制作实例 创建新的 属性 它创建的实例的dict get set 实例DICT中的函数可以引用。

    你的 make_my_class 定义没有多大意义。它有多余的 pass 声明,以及 make_class({'__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'))
    

    输出

    Creating class with attributes 0xb71e67d4
    Created instance attributes 0xb71373ec
    
    CLASS GET_VALUE __init__ from 0xb71e67d4
    Calling init of 0xb7137414 on 0xb71373c4 with ('Jim',)
    INIT 0xb71373c4 ('Jim',)
    Created instance attributes 0xb7137374
    
    CLASS GET_VALUE __init__ from 0xb71e67d4
    Calling init of 0xb7137414 on 0xb713734c with ('Fred',)
    INIT 0xb713734c ('Fred',)
    CLASS 0xb7137414
    
    INSTANCE 0xb71373c4
    INSTANCE GET_VALUE data from 0xb71373ec
    ('Jim',)
    INSTANCE GET_VALUE test from 0xb71373ec
    Hello
    
    INSTANCE 0xb713734c
    INSTANCE GET_VALUE data from 0xb7137374
    ('Fred',)
    INSTANCE GET_VALUE test from 0xb7137374
    Default Test