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

标签 python python-3.x python-2.7 class sicp

我试图理解 python 类系统实现中的初始化函数,取自这本书 (SICP python - reference to book section) .

init_instance(初始化)函数 """返回一个类型为 cls 的新对象,用 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):将类定义中的函数绑定(bind)到对象实例,以在 python 类实例中模拟 python 方法。如果值不可调用,则返回值(来自父类的 python 属性)。
  • make_class (attributes, base_class = None):设置一个类的行为,具有从另一个类继承的能力。以与 make_instance 类似的方式使用 get 和 set to,不同之处在于它不需要 bind_method。它使用 init_instance(cls, *args) 创建一个具有任意数量参数(用于属性方法)的新对象实例。 init_instancecls 参数将类调度字典传递给对象实例。因此,对象“继承”(缺少更好的词)类特征。
  • init_instance(cls, *args):这里我有点不确定。首先,该函数使用instance = make_instance(cls)创建一个实例,该实例通过cls字典继承类的特性。 init = cls['get']('__init__') , init 被创建,一个查询是否传入了 __init__ 关键字的语句make_class 的属性, , if init: init(instance, *args) 使 args 成为实例的本地参数?返回一个实例。

我可以将我的问题缩小到 -

init_instancemake_classnew(*args)的返回。这意味着实例字典返回给 new(*args)。但是,make_class 返回 cls,这意味着我们必须以某种方式更新 cls 以包含 instance 属性。那是怎么做到的?很可能是这条语句 init (instance, *args) 但我不知道如何分解这条语句。我还没有看到 init 是 fn,参数是如何传递给它的?

最佳答案

这段代码有点棘手,因此您会发现其中的一些内容令人费解也就不足为奇了。要理解它,你需要理解closures . this answer 中有一些关于 Python 闭包的信息.

init_instance 使用 instance = make_instance(cls) 创建一个新实例,然后它查找 cls< 的 init 方法,如果它存在,它会使用新实例和 args 中传递的任何内容调用 init 方法。 make_instanceinit_instance 都不会修改 cls 字典,或者传递给 make_class< 的 attributes 字典cls 创建时。实际发生的是,每次调用 make_instance 都会为其创建的实例创建一个新的 attributes 字典,getset 实例字典中的函数可以引用。

您的 make_my_class 定义没有多大意义。它有一个冗余的 pass 语句,并且 make_class({'__init__': __init__}) 不会工作,因为你还没有定义 __init__在任何地方,它都需要是一个函数来初始化你的类实例。

这是您的代码的修改版本。我为 my_class 创建了一个简单的 __init__ 函数,并添加了几个 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

关于python - 类实例实现,初始化实例——来自SICP python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50769327/

相关文章:

python - 如何创建一个列表或一组 N 深对象中的每个排列

python - Windows XP 上的 Scrapy ImportError : No module named w3lib. html

python - Django:使用 user.get_profile()

python - 如何在非主线程 QObject 中开始工作

python - 如何在 python 2.7.6 中导入 _ssl?

python - (discord.py) 如何检测自定义和默认表情符号

python - 使用 subprocess 模块的字符串参数

python - 为什么 Python 循环变慢?

python - Csv 文件并为字典提供某些键

python - 在 Django 中导入 python 模块 : __init__. py 类未加载