Я беру
A.__new__(B)
для обозначения «использовать метод создания A
объекта для создания (неинициализированного) B
объекта».
В каких случаях Я могу / должен использовать такие способности?
Подробнее
Вопрос о когда можно использовать some_cls.__new__(some_other_cls)
возможности
Но поскольку респонденты утверждают, что само использование __new__
, вероятно, вводится в заблуждение, я покажу ситуацию, когда я (возможно, заблуждающийся) считаю, что использование __new__
может быть хорошей идеей.
Фактический контекст таков. из json -сериализации моделей scikit-learn
таким образом, что граничное устройство может десериализовать и запустить целевой метод (например, «прогнозировать»). Здесь есть два важных аспекта: (1) scikit-learn
классы оценки '__init__
принимают параметры, касающиеся подбора модели, но атрибуты, необходимые для запуска метода predict
, динамически создаются в методе fit
, и (2) предпочтительна облегченная сериализованная модель, а на периферийном устройстве, вероятно, выполняется облегченная функция (не исходный метод scikit-learn
.
Я надеюсь, что приведенный ниже код достаточно точно иллюстрирует эту ситуацию:
class Greeter:
def __init__(self, greet):
self.greet = greet
def fit(self, this):
self.greet_this_ = self.greet + ' ' + this
def __call__(self):
if not hasattr(self, 'greet_this_'):
raise ValueError("Greeter not fit")
return self.greet_this_
obj = Greeter("hello")
obj.fit('world')
assert obj() == 'hello world'
Вот код сериализации:
import json
def serialize(obj, needed_attrs):
return json.dumps({a: getattr(obj, a) for a in needed_attrs})
class MethodLess: ...
def deserialize(obj_json, cls=MethodLess):
obj = cls.__new__(cls) # make the (unintialized) instance
# Note: couldn't do obj = cls() because cls might need some inputs
for k, v in json.loads(obj_json).items(): # fill it with it's attributes
setattr(obj, k, v)
return obj
obj_json = serialize(obj, ['greet_this_'])
deserialized_obj = deserialize(obj_json, cls=Greeter)
assert deserialized_obj() == 'hello world' == obj()
Но нам даже не нужен исходный класс, только метод, который нам нужно вызвать.
class MinimalGreeter:
def __call__(self):
if not hasattr(self, 'greet_this_'):
raise ValueError("Greeter not fit")
return self.greet_this_
obj_json = serialize(obj, ['greet_this_'])
deserialized_obj = deserialize(obj_json, cls=MinimalGreeter)
assert deserialized_obj() == 'hello world' == obj()
Эквивалентно, в функциональном форма ...
def call(self):
if not hasattr(self, 'greet_this_'):
raise ValueError("Greeter not fit")
return self.greet_this_
obj_json = serialize(obj, ['greet_this_'])
deserialized_obj = deserialize(obj_json, cls=MethodLess)
assert call(deserialized_obj) == 'hello world' == call(obj) == obj()