变量的符号链接

时间:2018-07-14 17:18:14

标签: python python-3.x

我正在开发一个程序,希望不时报告特定变量的状态,但是,我不一定知道我需要先验哪些变量。我研究过的其他程序(在C ++中)使用注册系统,在该系统中,相关变量一次在中央输出处理器中注册,然后在需要报告程序状态时,中央模块从输出变量中收集数据并将其写入输出文件。因此,程序流程将是这样的。

示例MyModule.py

from OutputProcessor import OutputProcessor


class MyClass():

    def __init__(self):
        op = OutputProcessor()

        # variable I want to report
        self.foo = None

        # register with output processor
        op.register_output_variable(self.foo, "Foo")

    def calc_foo(self, bar, rand):
        self.foo = bar ** rand

示例OutputProcessor.py

class OutputProcessor(object):
    # list or dict object containing the name and link information to variables of interest
    output_vars_data = []

    def __init__(self):
        pass

    def register_output_variable(self, var, name):
        OutputProcessor.output_vars_data.append({"link address": id(var), "name": name})

    def report_output(self):
        for data in OutputProcessor.output_vars_data:
            self.write_to_output_file(data)

    def write_to_output_file(self, data):
        # write all of the data to the output file here
        pass

示例Main.py

import random

from MyClass import MyClass
from OutputProcessor import OutputProcessor as OP

if __name__ == "__main__":

    cls_instance = MyClass()

    for i in range(100):
        cls_instance.calc_foo(i, random.randint(1, 10))
        OP().report_output()

我的第一个问题:这是否可能或可行?第二,如果是这样,我将如何去做?需要处理一些细微差别,例如如何处理报告相同变量的同一类的多个实例,但这似乎是一个小问题。有没有一种方法可以实现这一点,这样我就可以始终获取变量的当前值,而不仅仅是它的旧版本?

有什么想法或建议吗?

1 个答案:

答案 0 :(得分:2)

除了代码中的范围界定问题外,确实要记住一个问题。 Python通过将名称绑定到引用来完成所有工作。您有兴趣获取分配给名称的值,而不是分配给注册时可能已绑定到的引用的值。这有点像C和C ++中的指向指针的指针。

要跟踪任意名称,还需要跟踪其包含的名称空间。这样,您可以使用通用函数getattr来获取名称的最新值。命名空间可以是任何实例(模块和类也是实例)。

您的注册方法需要跟踪包含感兴趣的名称,名称本身以及您想要将其显示为的键的对象:

op.register_output_variable(self, 'foo', "Foo")

管理器类可以将值存储在字典中。我建议使用tuplecollections.namedtuple来代替“嵌套字典”来容纳“指针”:

def register_output_variable(self, inst, attr, key):
    self.output_vars_data[key] = (inst, attr)

输出变量时,请执行类似的操作

for key, spec in self.output_vars_data.items():
    print(key, '=', getattr(*spec))

这是为您提供一种通过名称而不是引用来引用对象属性的方法。如果您设置x.a = 1,注册x.a,然后再进行x.a += 1,则希望获得2作为您的值。要记住的重要一点是,x.a将绑定到其他引用,因为整数在Python中是不可变的。通过将x注册为名称空间,并将'a'注册为名称,可以完全绕开它。

您可以通过添加一种方法来进一步概括,该方法用于注册可索引元素,例如列表的元素和字典的值。您将注册实例和索引/键,而不是实例和属性名称。看看operator.attrgetteroperator.itemgetter以获得更多想法。

这只是一个广泛的建议。它不能解决您使用的静态,类和实例名称空间不一致的情况。