我采用
A.__new__(B)
意思是";使用CCD_ 1对象创建方法来制作(未初始化的(CCD_;。
我可以/应该在哪些用例中使用这些能力?
更多详细信息
问题是关于何时可以使用some_cls.__new__(some_other_cls)
功能
但是,由于响应者声称__new__
的使用可能被误导了,我将展示一种情况,即我(可能被误导(认为使用__new__
可能是个好主意。
实际上下文是json序列化scikit-learn
模型的上下文,边缘设备可以反序列化并运行目标方法(例如"predict"(。这里有两个重要方面:(1(scikit-learn
估计器类的__init__
采用了与模型拟合有关的参数,但运行predict
方法所需的属性是在A
0方法中动态生成的;(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()
我会在类本身中保留如何(反(序列化对象的详细信息。然后反序列化可以对JSON blob进行解码,并提取需要传递给__init__
的值。例如:
import json
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_
def to_json(self):
return json.dumps({'greet': self.greet, 'greet_this_': self.greet_this_)
@classmethod
def from_json(cls, obj_json):
d = json.loads(obj_json)
obj = cls(d['greet'])
obj.fit(d['greet_this_'])
return obj
obj = Greeter("hello")
obj.fit('world')
assert obj() == 'hello world'
obj_json = obj.to_json()
deserialized_obj = Greeter.from_json(obj_json)
assert deserialized_obj() == 'hello world' == obj()
我想不出你为什么要直接调用__new__
。但是,如果您想知道为什么您可能会从__new__
返回不同的类型,那么一个例子是根据传递的构造函数参数返回代理对象或不同的实现。换句话说,它可以作为工厂模式的替代品。
编辑:一个示例,根据要求:
class _StandardSolver:
def solve(self, x):
print('Using standard algorithm')
return x + 1
class _SpecialSolver:
def solve(self, x):
print('Using special algorithm')
return x * x # Imagine this algorithm is much more complicated, relying on a lot of class state, etc.
class ComplicatedProblemSolver:
def __new__(cls, use_special_algo, *args, **kwargs):
if use_special_algo:
return _SpecialSolver(*args, **kwargs)
else:
return _StandardSolver(*args, **kwargs)
if __name__ == '__main__':
solver = ComplicatedProblemSolver(use_special_algo=True)
print('Solution:', solver.solve(5))