Python 如何访问traits.api.Dict()下的字典?

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

下面是一个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
好的,我在这个问题中找到了答案:

将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()
是的,这只是一个输入错误,抱歉,没问题,我只是想让你知道,这样你就可以为出现同样问题的任何其他人修复它。;)