Реализация экземпляра класса, инициализация экземпляра - из SICP Python
Я пытаюсь понять функцию инициализации в реализации системы классов Python, взятую из этой книги (SICP python - ссылка на раздел книги).
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)
: принимает "класс" ->cls
Аргумент (сам словарь fxn сообщения) и описывает поведение объекта, то есть предоставляет необходимые свойства, чтобы вести себя аналогично объекту python. Мы можем установить атрибуты, которые остаются локальными для словаря атрибутов, используя 'set
". С помощьюget
Если атрибут не находится в объекте, он ищется в определении класса иbind_method
функция называется.bind_method(value,instance)
: связывает функцию в определении класса с экземпляром объекта для эмуляции методов python в экземпляре класса python. если значение не вызывается, возвращает значение (атрибут python из родительского класса).make_class (attributes, base_class = None)
Устанавливает поведение класса с возможностью наследования от другого класса. Использует get и set аналогично make_instance, за исключением того, что для него не требуется bind_method. Оно используетinit_instance(cls, *args)
создать новый экземпляр объекта с произвольным числом аргументов (для методов атрибутов).cls
аргумент в пользуinit_instance
передает словарь диспетчеризации классов экземпляру объекта. Следовательно, объект "наследует" (из-за отсутствия лучшего слова) признаки класса.init_instance(cls, *args)
: Здесь я немного не уверен. Во-первых, функция создает экземпляр сinstance = make_instance(cls)
экземпляр наследует свойства класса черезcls
толковый словарь.init = cls['get']('__init__')
,init
создается заявление, которое смотрит вверх, если__init__
ключевое слово было передано в атрибутахmake_class
,,if init: init(instance, *args)
делает аргументы локальными для экземпляра? Возвращает экземпляр
Я могу сузить свой вопрос до -
init_instance
это возврат к new(*args)
в make_class
, Что означает, что экземпляр словаря возвращается new(*args)
, Тем не мение, make_class
возвращается cls
что означает, что мы должны обновить cls
как-то содержать instance
свойства. Как это делается? Скорее всего это утверждение init (instance, *args)
но я не знаю, как сломать это утверждение. Я не видела init
как fn, как аргументы передаются ему?
1 ответ
Этот код немного хитрый, поэтому неудивительно, что некоторые из них вас озадачивают. Чтобы понять это, вам нужно понять замыкания. В этом ответе есть некоторая информация о замыканиях в Python.
init_instance
создает новый экземпляр с instance = make_instance(cls)
затем он смотрит вверх init
метод cls
и, если он существует, он называет это init
метод с новым экземпляром и все, что было передано в args
, ни make_instance
ни init_instance
изменить cls
словарь, или attributes
словарь, который был передан make_class
когда cls
был создан. На самом деле происходит то, что каждый вызов make_instance
создает новый attributes
диктовать для экземпляра, который он создает, который get
а также set
функции в экземпляре dict могут ссылаться.
Ваш 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'))
выход
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