【问题标题】:How do I update the dictionary of a mapped trait, after I've already constructed it?在我已经构建映射特征的字典之后,如何更新它?
【发布时间】:2019-09-22 14:13:29
【问题描述】:

我需要在初始特征创建后的某个时间更新映射特征的字典。 我该怎么做呢? 以下代码:

from traits.api import (HasTraits, Trait)

class bar(HasTraits):
    zap = Trait("None", {"None": None})

    def __init__(self):
        # In reality, determined programmatically at runtime.
        add_dict_entries = {"One": 1}
        new_dict = {"None": None}
        new_dict.update(add_dict_entries)
        self.zap = Trait("None", new_dict)

theBar = bar()

产量:

Traceback (most recent call last):
  File "tst_mapped_trait.py", line 13, in <module>
    theBar = bar()
  File "tst_mapped_trait.py", line 11, in __init__
    self.zap = Trait("None", new_dict)
  File "C:\Users\dbanas\Anaconda3\envs\pybert-dev\lib\site-packages\traits\trait_handlers.py", line 236, in error
    object, name, self.full_info(object, name, value), value
traits.trait_errors.TraitError: The 'zap' trait of a bar instance must be 'None', but a value of <traits.traits.CTrait object at 0x00000000034AA9E8> <class 'traits.traits.CTrait'> was specified.```

【问题讨论】:

    标签: python traits enthought traitsui


    【解决方案1】:

    好的,下面的代码成功了:

    from traits.api import (HasTraits, Trait)
    
    class bar(HasTraits):
        zap = Trait("None", {"None": None})
    
        def __init__(self):
            # In reality, determined programmatically at runtime.
            add_dict_entries = {"One": 1}
            new_dict = {"None": None}
            new_dict.update(add_dict_entries)
            # self.zap = Trait("None", new_dict)
            # self.zap.update(new_dict)
            # self.trait_setq(zap=Trait("None", new_dict))
            self.remove_trait("zap")
            self.add_trait("zap", Trait("None", new_dict))
    
    theBar = bar()
    

    注意:注释掉的行是我尝试过的,不起作用

    【讨论】:

      【解决方案2】:

      我不确定我是否了解您的需求,但我可以提出一些建议:

      1. 如果您同时允许NoneDict,那么Either 是一个不错的选择。
      2. 使用dynamic initialization 在运行时为特征创建一个值。最好使用__init__ 方法。
      3. 如果您真的需要 __init__ 方法,您必须在其中调用 super 以使 Traits 正常工作,例如`super()init(*args, **kwargs)

      这是您的代码版本,我认为可以解决您的问题。

      from traits.api import (HasTraits, Either, Dict)
      
      class bar(HasTraits):
          zap = Either(None, Dict)
      
          def _zap_default(self):
              add_dict_entries = {"One": 1}
              new_dict = {"None": None}
              new_dict.update(add_dict_entries)
              return new_dict
      
      theBar = bar()
      print(theBar.zap)
      

      这里有一些关于无效代码的反馈。下面的self.zap = Trait("None", new_dict) 行不起作用,因为它试图创建一个Trait 对象,但self.zap 只接受NoneDict。我的建议是仅在类级别使用特征定义进行打字。在方法中,使用常规的 Python 类型。

      from traits.api import (HasTraits, Trait)
      
      class bar(HasTraits):
          zap = Trait("None", {"None": None})
      
          def __init__(self):
              # In reality, determined programmatically at runtime.
              add_dict_entries = {"One": 1}
              new_dict = {"None": None}
              new_dict.update(add_dict_entries)
              self.zap = Trait("None", new_dict)
      
      theBar = bar()
      

      【讨论】:

      • 感谢您的回复!回应您的编号点: 1. 我不想要Either,只想要Dict。 2.动态初始化仍然只允许我定义一次特征内容;我需要在程序执行期间多次重新定义特征内容。 3. 是的,对不起,我应该在我的示例代码中包含它,以确保完全正确。我不清楚您提出的解决方案如何解决我的问题,因为我需要在程序执行期间多次重新定义 Trait 的内容。
      【解决方案3】:

      这是给定original poster's comment的第二次尝试

      如果您希望zap 的类型为Dict 且仅为Dict,则将其定义为这样。如果初始值在运行时不必是计算机,您也可以内联:

      >>> from traits.api import HasTraits, Dict
      >>> class Bar(HasTraits):
      ...     zap = Dict({5: 'e'})
      ...
      >>> bar = Bar()
      >>> bar.zap
      {5: 'e'}
      

      如果需要在运行时计算,则使用dynamic initialization初始化值:

      >>> class Bar(HasTraits):
      ...     zap = Dict()
      ...
      ...     def _zap_default(self):
      ...         default = {}
      ...         default[1] = 'a'
      ...         return default
      ...
      >>> bar_dynamic = Bar()
      >>> bar_dynamic.zap
      {1: 'a'}
      

      无论哪种方式,一旦类被实例化(bar = Bar() 之后),Bar 实例上的zap 属性就是一个常规字典。您应该在实例化后使用 Trait 类型,仅使用常规 Python 对象。特征用于定义和强制类型。您分配给类型化特征的对象的 type()(如此处的 zap)是常规 Python 类型。

      以下是您在课堂外修改 zap 的方法:

      >>> bar.zap[2] = 'b'
      >>> bar.zap
      {5: 'e', 2: 'b'}
      >>>
      >>> bar_dynamic.zap[3] = 'c'
      >>> bar_dynamic.zap
      {1: 'a', 3: 'c'}
      

      现在从类内部,作为self 的常规属性:

      >>> class Bar(HasTraits):
      ...     zap = Dict()
      ...
      ...     def _zap_default(self):
      ...         default = {}
      ...         default[1] = 'a'
      ...         return default
      ...
      ...     def add_pair(self, key, value):
      ...         self.zap[key] = value
      ...
      >>> bar_method = Bar()
      >>> bar_method.zap
      {1: 'a'}
      >>> bar_method.add_pair(26, 'z')
      >>> bar_method.zap
      {1: 'a', 26: 'z'}
      

      【讨论】:

      • 感谢您继续尝试帮助我解决此问题!我担心我在清楚地解释我想要什么方面做得很糟糕。所以,我又试了一次,从头开始:stackoverflow.com/questions/59010527/…
      猜你喜欢
      • 1970-01-01
      • 2018-08-19
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-28
      • 2020-05-27
      • 2018-07-05
      相关资源
      最近更新 更多