首页 > 解决方案 > 我将如何“听”/装饰导入类中的设置器

问题描述

我不确定这是否是一种很好的使用方法,但我对 Python 的经验并不丰富,所以请接受我的道歉。我试图对此进行一些研究,但其他相关问题已经给出了替代的特定问题的解决方案——这些都不适用于我的具体案例。

我有一门课来处理我的特定机器学习模型的训练/查询。None该算法在远程传感器上运行,如果算法未经过训练,则将各种值输入返回的对象中。训练后,它会根据分配给新输入的分类返回True或返回。False有时,该类会更新几个阈值参数,我需要知道何时发生这种情况。

我正在使用套接字将消息从远程传感器传递到我的主服务器。我不想通过填充消息传递代码来使 ML 算法类复杂化,因此我一直在Main导入“算法”类的类中处理这个问题。我希望Main该类能够确定阈值参数何时更新并将其报告回服务器。

class MyAlgorithmClass:

    def feed_value(self):
         ....


class Main:

    def __init__(self):
        self._algorithm_data = MyAlgorithmClass()
        self._sensor_data_queue = Queue()

    def process_data(self):
        while True:
            sensor_value = self._sensor_data_queue.get()
            result, value = self._algorithm_data.feed_value(sensor_value)
            if result is None:
                # value represents % training complete
                self._socket.emit('training', value)
            elif result is True:
                # value represents % chance that input is categoryA
                self._socket.emit('categoryA', value)
            elif result is False:
                ...

我最初的想法是MyAlgorithmClass使用 setter 添加一个属性。然后我可以在我的班级中装饰它,Main以便每次调用 setter 时,我都可以使用该值......例如:

class MyAlgorithmClass:
    
    @property
    def param1(self):
        return self._param1

    @param1.setter
    def param1(self, value):
        self._param1 = value


class Main:

    def __init__(self):
        self._algorithm_data = MyAlgorithmClass()
        self._sensor_data_queue = Queue()    

        def watch_param1(func):
            def inner(*args):
                self._socket.emit('param1_updated', *args)
            func(*args)

我现在的问题是如何self._algorithm_data.param1用 装饰二传手watch_param1?如果我只是简单地设置self._algorithm_data.param1 = watch_param1,那么我最终将设置self._algorithm_data._param1等于我的功能,这不是我想要做的。

我可以使用 getter/setter 方法而不是属性,但这不是很pythonic,并且由于多人正在修改此代码,我不希望稍后其他人为属性替换/更改这些方法。

这里最好的方法是什么?这是一个小例子,但稍后我会有稍微复杂一点的例子,我不想要会导致算法类过于复杂的东西。显然,另一种选择是观察者模式,但我不确定在某些情况下我只有一个变量要监控的地方有多合适。

我真的很难找到一个好的解决方案,所以任何建议都将不胜感激。

提前致谢,

汤姆

标签: pythonpython-3.xpropertiesobserver-patternpython-socketio

解决方案


使用描述符。它们允许您在 Python 中自定义属性查找、存储和删除。

带有描述符的代码的简化玩具版本如下所示:

class WatchedParam:
    def __init__(self, name):
        self.name = name
        
    def __get__(self, instance, insttype=None):
        print(f"{self.name} : value accessed")
        return getattr(instance, '_' + self.name)
    
    def __set__(self, instance, new_val):
        print(f"{self.name} : value set")
        setattr(instance, '_' + self.name, new_val)

class MyAlgorithmClass:
    param1 = WatchedParam("param1")
    param2 = WatchedParam("param2")

    def __init__(self, param1, param2, param3):
        self.param1 = param1
        self.param2 = param2
        self.param3 = param3

class Main:
    def __init__(self):
        self._data = MyAlgorithmClass(10, 20, 50)

m = Main()
m._data.param1 # calls WatchedParam.__get__
m._data.param2 = 100 # calls WatchedParam.__set__

该类WatchedParam是一个描述符,可用于MyAlgorithmClass指定需要监控的参数。


推荐阅读