Этот код немного хитрый, поэтому неудивительно, что вы находите его немного загадочным.Чтобы понять это, вам нужно понять замыкания .Есть некоторая информация о замыканиях в Python в этом ответе .
init_instance
создает новый экземпляр с instance = make_instance(cls)
, затем ищет метод init
cls
иесли он существует, он вызывает метод init
с новым экземпляром и всем, что было передано в args
.Ни make_instance
, ни init_instance
не изменяют словарь cls
или словарь attributes
, которые были переданы в make_class
при создании cls
.На самом деле происходит то, что каждый вызов make_instance
создает новый attributes
dict для экземпляра, который он создает, на который могут ссылаться функции 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'))
output
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