Python 变量的符号链接
我正在做一个程序,我想不时报告特定变量的状态,但是,我不一定知道我需要哪些变量。我所研究的其他程序(在C++中)使用注册系统,其中感兴趣的变量向中央输出处理器注册一次,然后当需要报告程序状态时,中央模块从输出变量收集数据并写入输出文件。所以,程序流程应该是这样的 示例Python 变量的符号链接,python,python-3.x,Python,Python 3.x,我正在做一个程序,我想不时报告特定变量的状态,但是,我不一定知道我需要哪些变量。我所研究的其他程序(在C++中)使用注册系统,其中感兴趣的变量向中央输出处理器注册一次,然后当需要报告程序状态时,中央模块从输出变量收集数据并写入输出文件。所以,程序流程应该是这样的 示例MyModule.py from OutputProcessor import OutputProcessor class MyClass(): def __init__(self): op = Out
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
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
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()
示例OutputProcessor.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
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
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()
示例Main.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
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
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通过将名称绑定到引用来完成所有工作。您感兴趣的是获得分配给名称的值,而不是它在注册时可能已绑定到的引用。这有点像C和C++中的一个pto to a指针。 要跟踪任意名称,还需要跟踪它们的封闭名称空间。这样,您就可以使用通用函数
getattr
获取您姓名的最新值。命名空间可以是任何实例(模块和类也是实例)
您的注册方法需要跟踪包含感兴趣的名称、名称本身以及要将其显示为的密钥的对象:
op.register_output_variable(self, 'foo', "Foo")
manager类可以将值存储在字典中。我建议使用tuple
或collections.namedtuple
来保存“指针”,而不是嵌套字典:
当您输出变量时,执行如下操作
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.attrgetter
和operator.itemgetter
了解更多想法
这只是一个宽泛的建议。它没有解决您正在使用的静态、类和实例名称空间不一致的问题。您将calc_foo定义为类的方法,而不是纯函数。你不能这样称呼它。但是您可以将其定义为
@staticmethod
,并像使用MyClass.calc\u foo()
“从MyClass导入calc\u foo”一样使用它。这不可能始终通过引用导入methodPython works。当您使用不可变类时,这仍然会有问题。请查看操作员模块中的attrgetter。@PM2Ring yes,谢谢。我希望现在更清楚了。本质上,我希望能够用我的register_var函数注册任意成员变量,然后在程序运行期间的任何时候报告这些变量的状态。正如Mad Physician所解释的,在Python中做这种事情并不容易。Python变量不像C++变量,数据模型非常不同。您可能会发现这篇文章很有帮助:,它是由资深的Ned Batchelder撰写的。谢谢您的评论和建议。我将根据您提供的内容在此基础上进行更多的原型设计。目前,我认为我不需要在列表或字典中注册元素。关于范围界定问题,我显然“不知道我不知道什么”。我自己很少接受过正式的CS或编程培训,如果能就如何改进我的示例提出建议,我将不胜感激,这样我就能更好地理解应该如何做。