我正在开发一个程序,我想不时报告特定变量的状态,但是,我不一定知道我需要先验哪些变量。我开发的其他程序(用 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()
我的第一个问题:这是否可能或可行?其次,如果是这样,我将如何去做?需要处理一些细微差别,例如如何处理报告相同变量的同一类的多个实例,但这似乎是一个小问题。有没有办法实现这个,以便我始终获得变量的当前值,而不仅仅是它的旧副本?
有什么想法或建议吗?
最佳答案
除了代码中的范围问题之外,还有一个问题需要牢记。 Python 通过将名称绑定(bind)到引用来完成所有操作。您感兴趣的是获取分配给名称的值,而不是分配给它在注册时可能绑定(bind)的引用。这有点像 C 和 C++ 中的指针到指针。
要跟踪任意名称,您还需要跟踪它们的封闭 namespace 。这样您就可以使用通用函数 getattr
来获取您姓名的最新值。命名空间可以是任何实例(模块和类也是实例)。
您的注册方法需要跟踪包含感兴趣名称的对象、名称本身以及您想要将其显示为的键:
op.register_output_variable(self, 'foo', "Foo")
管理器类可以将值存储在字典中。我建议使用 tuple
或 collections.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
将绑定(bind)到不同的引用,因为整数在 Python 中是不可变的。您可以通过将 x
注册为命名空间,将 'a'
注册为名称来完全绕过此问题。
您可以通过添加注册可索引元素的方法来进一步概括,例如列表的元素和字典的值。您将注册实例和索引/键,而不是实例和属性名称。请查看 operator.attrgetter
和 operator.itemgetter
了解更多想法。
这只是一个广泛的建议。它不能解决您正在使用的静态、类和实例命名空间不一致的困惑问题。
关于python - 变量的符号链接(symbolic link),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51341690/