Python 如何访问traits.api.Dict()下的字典?
下面是一个shell失败的示例Python 如何访问traits.api.Dict()下的字典?,python,traits,traitsui,Python,Traits,Traitsui,下面是一个shell失败的示例 >>> from traits.api import Dict >>> d=Dict() >>> d['Foo']='BAR' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'Dict' object does not support item assignment
>>> from traits.api import Dict
>>> d=Dict()
>>> d['Foo']='BAR'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Dict' object does not support item assignment
好的,我在这个问题中找到了答案:
将Dict或List对象作为属性包含在类中时,不应这样做:
class Foo(HasTraits):
def __init__(self):
### This will not work as expected!
self.bar = Dict(desc='Description.', label='Name', value={})
而是这样做:
class Foo(HasTraits):
def __init__(self):
self.add_trait('bar', Dict(desc='Description.', label='Name', value={}) )
现在,以下措施将起作用:
>>> f = Foo()
>>> f.bar['baz']='boo'
>>> f.bar['baz']
'boo'
不幸的是,由于某些原因,使用configure_traits()生成的GUI在底层数据更改时不会更新其视图。下面是一些演示问题的测试代码:
import os
import time
import sys
from traits.api import HasTraits, Str, Dict
from traitsui.api import View, Item, ValueEditor
class displayWindow(HasTraits):
def __init__(self, **traits):
super(displayWindow, self).__init__(**traits)
self.add_trait('_remote_data', Dict(desc='Dictionary to store remote data in.', label='Data', value={}) )
self.add_trait('_messages', Str(desc='Field to display messages to the user.', label='Messages', multi_line=True, value='') )
def traits_view(self):
return View(
Item('object._remote_data', editor=ValueEditor()),
Item('object._messages'),
resizable=True
)
class testObj(object):
def __init__(self):
super(testObj, self).__init__()
self._display = displayWindow()
self._ui_pid = 0
def run(self):
### Run the GUI in the background
self._ui_pid = os.fork()
if not self._ui_pid:
self._display.configure_traits()
i = 0
while True:
self._display._remote_data[str(i)] = i
msg = 'Added (key,value):\t("%s", %s)\n' % (str(i), i, )
self._display._messages += msg
sys.stderr.write(msg)
time.sleep(5.0)
i+=1
if __name__ == '__main__':
f = testObj()
f.run()
好的,我在这个问题中找到了答案:
将Dict或List对象作为属性包含在类中时,不应这样做:
class Foo(HasTraits):
def __init__(self):
### This will not work as expected!
self.bar = Dict(desc='Description.', label='Name', value={})
而是这样做:
class Foo(HasTraits):
def __init__(self):
self.add_trait('bar', Dict(desc='Description.', label='Name', value={}) )
现在,以下措施将起作用:
>>> f = Foo()
>>> f.bar['baz']='boo'
>>> f.bar['baz']
'boo'
不幸的是,由于某些原因,使用configure_traits()生成的GUI在底层数据更改时不会更新其视图。下面是一些演示问题的测试代码:
import os
import time
import sys
from traits.api import HasTraits, Str, Dict
from traitsui.api import View, Item, ValueEditor
class displayWindow(HasTraits):
def __init__(self, **traits):
super(displayWindow, self).__init__(**traits)
self.add_trait('_remote_data', Dict(desc='Dictionary to store remote data in.', label='Data', value={}) )
self.add_trait('_messages', Str(desc='Field to display messages to the user.', label='Messages', multi_line=True, value='') )
def traits_view(self):
return View(
Item('object._remote_data', editor=ValueEditor()),
Item('object._messages'),
resizable=True
)
class testObj(object):
def __init__(self):
super(testObj, self).__init__()
self._display = displayWindow()
self._ui_pid = 0
def run(self):
### Run the GUI in the background
self._ui_pid = os.fork()
if not self._ui_pid:
self._display.configure_traits()
i = 0
while True:
self._display._remote_data[str(i)] = i
msg = 'Added (key,value):\t("%s", %s)\n' % (str(i), i, )
self._display._messages += msg
sys.stderr.write(msg)
time.sleep(5.0)
i+=1
if __name__ == '__main__':
f = testObj()
f.run()
我认为您的基本问题与存在于模型对象之外的特性的通知问题有关,而不是与“如何访问这些对象”本身有关[编辑:事实上,不,这根本不是你的问题!但当我带着对我以前见过的问题的偏见阅读你的问题时,我以为你是在试图这样做,无论如何,我建议的解决方案仍然有效。)我最近遇到了这类问题,因为我决定如何设计我的程序(代码描述的GUI模块化地与它可以包含的非常复杂的数据集分离)。您可能已经找到了我的其他问题,正如您找到第一个问题一样 traitsui为您的应用程序设计的设计不是让大量数据生活在远离GUI的复杂数据层次结构中,这会导致通知方面的各种问题。设计解决方案是采用更平坦的设计,将GUI信息更直接地集成到程序的不同部分 我认为,一般来说(我在中使用了一些示例),对于不涉及字典的问题,可能会有各种解决方法。我不确定什么是解决字典问题的最有利于设计的解决方案,但有一件事是可行的,不会对您的设计造成太多干扰(但这仍然是一个“有点烦人的问题”)解决方案)是将字典中的所有内容都标记为HasTraits,从而将其标记为listenable。如下所示:
from traits.api import *
from traitsui.api import *
from traitsui.ui_editors.array_view_editor import ArrayViewEditor
import numpy as np
class DContainer(HasTraits):
_dict=Dict
def __getattr__(self, k):
if k in self._dict:
return self._dict[k]
class DItem(HasTraits):
_item=Any
def __init__(self,item):
super(DItem,self).__init__()
self._item=item
def setitem(self,val):
self._item=val
def getitem(self):
return self._item
def traits_view(self):
return View(Item('_item',editor=ArrayViewEditor()))
class LargeApplication(HasTraits):
d=Instance(DContainer)
stupid_listener=Any
bn=Button('CLICKME')
def _d_default(self):
d=DContainer()
d._dict={'a_stat':DItem(np.random.random((10,1))),
'b_stat':DItem(np.random.random((10,10)))}
return d
def traits_view(self):
v=View(
Item('object.d.a_stat',editor=InstanceEditor(),style='custom'),
Item('bn'),
height=500,width=500)
return v
def _bn_fired(self):
self.d.a_stat.setitem(np.random.random((10,1)))
LargeApplication().configure_traits()
我认为您的基本问题与存在于模型对象之外的特性的通知问题有关,而不是与“如何访问这些对象”本身有关[编辑:事实上,不,这根本不是你的问题!但当我带着对我以前见过的问题的偏见阅读你的问题时,我以为你是在试图这样做,无论如何,我建议的解决方案仍然有效。)我最近遇到了这类问题,因为我决定如何设计我的程序(代码描述的GUI模块化地与它可以包含的非常复杂的数据集分离)。您可能已经找到了我的其他问题,正如您找到第一个问题一样 traitsui为您的应用程序设计的设计不是让大量数据生活在远离GUI的复杂数据层次结构中,这会导致通知方面的各种问题。设计解决方案是采用更平坦的设计,将GUI信息更直接地集成到程序的不同部分 我认为,一般来说(我在中使用了一些示例),对于不涉及字典的问题,可能会有各种解决方法。我不确定什么是解决字典问题的最有利于设计的解决方案,但有一件事是可行的,不会对您的设计造成太多干扰(但这仍然是一个“有点烦人的问题”)解决方案)是将字典中的所有内容都标记为HasTraits,从而将其标记为listenable。如下所示:
from traits.api import *
from traitsui.api import *
from traitsui.ui_editors.array_view_editor import ArrayViewEditor
import numpy as np
class DContainer(HasTraits):
_dict=Dict
def __getattr__(self, k):
if k in self._dict:
return self._dict[k]
class DItem(HasTraits):
_item=Any
def __init__(self,item):
super(DItem,self).__init__()
self._item=item
def setitem(self,val):
self._item=val
def getitem(self):
return self._item
def traits_view(self):
return View(Item('_item',editor=ArrayViewEditor()))
class LargeApplication(HasTraits):
d=Instance(DContainer)
stupid_listener=Any
bn=Button('CLICKME')
def _d_default(self):
d=DContainer()
d._dict={'a_stat':DItem(np.random.random((10,1))),
'b_stat':DItem(np.random.random((10,10)))}
return d
def traits_view(self):
v=View(
Item('object.d.a_stat',editor=InstanceEditor(),style='custom'),
Item('bn'),
height=500,width=500)
return v
def _bn_fired(self):
self.d.a_stat.setitem(np.random.random((10,1)))
LargeApplication().configure_traits()
d._dict={'Foo':'BAR'}
?对d._dict的操作不会触发特征更改通知,因此GUI永远不会得到更新。正如我所说,除非事先知道dict并且不会修改它,否则该解决方案将无法工作。d._dict={'Foo':'BAR'}D.J.DICT上的操作不会触发特征改变通知,所以GUI永远不会得到更新。就像我说的那样,除非DICT预先知道并且不会被修改,否则解决方案将不起作用。我应该把它作为一个新问题发布吗?请原谅我的无知,我对这个站点是新的。我应该把它作为一个新问题发布吗?我不知道,我是这个网站的新手。谢谢!您的示例代码解决了我一直看到的问题。但需要注意的是,congigure_traits()只能在类实例上运行,而不能在类对象上运行,因此最后一行应该改为:LargeApplication()。configure_traits()
是的,这只是一个输入错误,对不起,没问题,我只是想让你知道,这样你就可以为其他碰巧遇到同样问题的人修复它了。;)谢谢!你的示例代码解决了我一直看到的问题。不过需要注意的是,congigure_traits()只能在类实例而不是类对象上运行,所以最后一行应该改为:LargeApplication()。configure_traits()
是的,这只是一个输入错误,抱歉,没问题,我只是想让你知道,这样你就可以为出现同样问题的任何其他人修复它。;)