简体   繁体   English

`A.__new__(B)` 的用例,即 python 中的“使用一个 class 制作另一个”

[英]Use cases for `A.__new__(B)` i.e. “using one class to make another” in python

I take我拿

A.__new__(B)

to mean "use the A object-creating method to make an (uninitialized) B object".意思是“使用A对象创建方法来制作(未初始化的) B对象”。

What are some use cases where I can/should use such abilities?在哪些用例中我可以/应该使用这些能力?

More details更多细节

The question is about when could one use the some_cls.__new__(some_other_cls) capabilities问题是何时可以使用some_cls.__new__(some_other_cls)功能

But since responders claim that the very use of __new__ is probably misled, I will show a situation where I'm (possibly misled) to think that using __new__ might be a good idea.但是由于响应者声称__new__的使用可能被误导,我将展示一个我(可能被误导)认为使用__new__可能是一个好主意的情况。

The actual context is that of json-serializing scikit-learn models in such a way that an edge device can deserialize and run a target method (eg 'predict').实际的上下文是 json 序列化scikit-learn模型的上下文,使得边缘设备可以反序列化并运行目标方法(例如“预测”)。 Two important aspects here: (1) scikit-learn estimator classes' __init__ takes parameters concerning the fitting of a model, but the attributes needed to run the predict method are dynamically made in fit method, and (2) a light weight serialized model is preferable, and the edge device is probably running a light weight function (not the original scikit-learn method.这里有两个重要方面:(1) scikit-learn估计器类的__init__采用与 model 的拟合有关的参数,但运行predict方法所需的属性是在fit方法中动态生成的,以及(2)轻量级序列化 Z20F35E630DAF44DFA4C3 更可取并且边缘设备可能正在运行轻量级 function (不是原来的scikit-learn方法。

I hope the code below illustrates this situation sufficiently faithfully:我希望下面的代码足够忠实地说明这种情况:

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'

Here's some serialization code:下面是一些序列化代码:

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()

But we don't even need the original class, just the method we need to call.但是我们甚至不需要原来的class,只需要我们需要调用的方法。

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()

Equivalently, in functional form...等效地,以函数形式...

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()

I can't think of any reason why you would want to call __new__ directly.我想不出您为什么要直接调用__new__的任何原因。 But if you are asking why you might return a different type from __new__ , one example would be to return a proxy object or a different implementation based on what constructor arguments are passed.但是,如果您要问为什么可能从__new__返回不同的类型,一个示例是返回代理 object 或基于传递的构造函数 arguments 的不同实现。 In other words it can be used as an alternative to the factory pattern.换句话说,它可以用作工厂模式的替代品。

EDIT: An example, as requested:编辑:一个例子,根据要求:

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))

I would keep the details of how you (de)serialize an object in the class itself.我会在 class 本身中保留您如何(反)序列化 object 的详细信息。 Then deserialization can decode the JSON blob and extract the values necessary to be passed to __init__ .然后反序列化可以解码 JSON blob 并提取需要传递给__init__的值。 For example:例如:

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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Pandas 测试一列是否是另一列的子集? (即 B 列包含 A 列) - Pandas test if one column is a subset of another column? (i.e. column B contains column A) 使用(Python)Webdriver选择文本而不使用元素(即单击并拖动以从一组坐标突出显示另一组坐标) - Using (Python) Webdriver to select text without using an element (i.e. click and drag to highlight from one set of coordinates to another set) 使用 Python 中的外部/帮助文件(即模块)修改 class 属性(自身)的最佳方法是什么? - What is the best way to modify a class attribute (self) using an external/helper file (i.e. module) in Python? 重用; 即,在 class 中的 python 数据生成器的 stream 中继续 - Reusing; i.e., continuing in stream of a python data generator in a class 是在“全局”类中定义的变量,即在Python中无效 - Is a variable defined in a class “global” i.e. invalid in Python 每次使用时如何设置 Django? (即使用 **source bin/activate** 和 ** python manage.py runserver**) - How to setup Django every time you use it? (i.e. using **source bin/activate** and ** python manage.py runserver**) 我将如何使Python识别字符串的类别(即不同的语法类型的单词) - How would I make Python recognize categories of strings (i.e. different grammatical types of words) 在创建新的 `type` 实例(即类)时,类 `type.__init__` 和 `type.__new__` 做了什么? - What does class `type.__init__` and `type.__new__` do when creating a new `type` instance(i.e. class)? 如何从python中的字符串中删除(真正的)最后一个字符? [即不创建新引用] - How do I remove (for real) the last character from a string in python? [i.e. NOT create a new reference] 如何获取用户输入来创建另一个类的实例? (即从用户规范中添加员工?) - How to take user input to create another instance of a class? (i.e. add an employee from user specifications?)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM