python - 如何在列表上触发 Traits 静态事件通知?

标签 python events traits enthought

我正在处理 traits presentation from PyCon 2010 .大约在 2 点 30 分 45 秒,主持人开始报道 trait event notifications ,它允许(除其他外)在任何时候自动调用子程序的能力 trait已经改变了。

我正在运行他给出的示例的修改副本......在这个试验中,我试图看看是否可以在我对 volume 进行更改时触发静态事件>volume_inputs.

# Filename: spinaltap.py
from traits.api import HasTraits, Range, List, Float
import traits

class Amplifier(HasTraits):
    """
    Define an Amplifier (ref -> Spinal Tap) with Enthought's traits.  Use traits
    to enforce values boundaries on the Amplifier's attributes.  Use events to
    notify via the console when the volume trait is changed and when new volume
    traits are added to inputs.
    """

    # Define a volume trait as a Float between 0.0 and 11.0 (inclusive)
    # see self._volume_changed()
    volume = Range(value=5.0, trait=Float, low=0.0, high=11.0)

    # Define an inputs trait as a List() containing volume traits
    volume_inputs = List(volume) # <-- fire a static trait notification
                             # when another volume element is added
                             # see self._volume_inputs_changed()

    def __init__(self, volume=5.0):
        super(Amplifier, self).__init__()
        self.volume = volume
        self.volume_inputs.append(volume)

    def _volume_changed(self, old, new):
        # This is a static event listener for self.volume
        #                                     ^^^^^^^^^^^
        if not (new in self.inputs):
            self.inputs.append(self.volume)
        if new == 11.0:
            print("This one goes to eleven... so far, we have seen", self.inputs)

    def _volume_inputs_changed(self, old, new):
        # This is a static event listener for self.volume_inputs
        #                                     ^^^^^^^^^^^^^^^^^^
        print("Check it out!!")

if __name__=='__main__':
    spinal_tap = Amplifier()
    candidate_volume = 4.0
    spinal_tap.event_fired = False
    print("- INITIAL_VALUE var volume_inputs = {}".format(spinal_tap.volume_inputs))
    print("- APPEND a new volume of 4.0")
    print("    - volume_inputs = {} # BEGIN".format(spinal_tap.volume_inputs))
    print("    - volume_inputs.append({})".format(candidate_volume))
    spinal_tap.volume_inputs.append(candidate_volume)
    print("    - volume_inputs: {} # END".format(spinal_tap.volume_inputs))
    if spinal_tap.event_fired is False:
        print("    - Test FAILED: Traits did not fire _volume_inputs_changed()")
    else:
        print("    - Test PASSED: Traits fired _volume_inputs_changed()")
    try:
        spinal_tap.event_fired = False
        print("- NEGATIVE Test... try to append 12.0.  This should fail; 12.0 is out of bounds")
        print("    - volume_inputs: {} # BEGIN".format(spinal_tap.volume_inputs))
        candidate_volume = 12.0
        print("    - volume_inputs.append({})".format(candidate_volume))
        spinal_tap.volume_inputs.append(candidate_volume)
        print("    - volume_inputs: {} # END".format(spinal_tap.volume_inputs))
        if spinal_tap.event_fired is False:
            print("    - Test FAILED: Traits did not fire _volume_inputs_changed()")
    except  traits.trait_errors.TraitError:
        print("    - TraitError raised --> HERE <--")
        print("    - volume_inputs: {} # END".format(spinal_tap.volume_inputs))
        print("    - Test PASSED: traits correctly raised TraitError instead of appending {}.".format(candidate_volume))

问题 -> 我从未看到来自 _volume_inputs_changed() 的任何事件。无论我编写什么示例,我都无法得到 List触发一个事件。

在下面的输出中,没有证据表明 _volume_inputs_changed() 曾经触发过。

[mpenning@Bucksnort ~]$ python spinaltap.py
- INITIAL_VALUE var volume_inputs = [5.0]
- APPEND a new volume of 4.0
    - volume_inputs = [5.0] # BEGIN
    - volume_inputs.append(4.0)
    - volume_inputs: [5.0, 4.0] # END
    - Test FAILED: Traits did not fire _volume_inputs_changed()
- NEGATIVE Test... try to append 12.0.  This should fail; 12.0 is out of bounds
    - volume_inputs: [5.0, 4.0] # BEGIN
    - volume_inputs.append(12.0)
    - TraitError raised --> HERE <--
    - volume_inputs: [5.0, 4.0] # END
    - Test PASSED: traits correctly raised TraitError instead of appending 12.0.
[mpenning@Bucksnort ~]$

应该 List()使用特征时能够触发静态 List() 事件(例如 _inputs_changed())?如果是这样,我做错了什么吗?

最佳答案

在浏览了他们的单元测试后,我在 enthought 的 event unittest coverage 中找到了一个针对 Dict 特性的测试。 ...

当你有一个像 traits.api.List()traits.api.Dict() 这样的 traits 容器时,你需要像这样设置魔术事件监听器方法名称:

# Magic event listener for the `traits.api.List()` called self.volume_inputs
def _volume_inputs_items_changed(self, old, new):
def _volume_inputs_items_changed(self, old, new):
    # This is a static event listener for --> self.volume_inputs <--
    if len(new.added) > 0:
        print "Check it out, we added %s to self.items" % new.added
    elif len(new.removed) > 0:
        print "Check it out, we removed %s from self.items" % new.removed

同样,我还发现 on_trait_change 装饰器(用于动态 traits 事件通知)如果您使用 traits.api 调用它,则需要类似的命名法.Listtraits.api.Dict...所以我也可以将上面的代码写成:

from traits.api import on_trait_change
# ...
@on_trait_change('volume_inputs_items')
def something_changed(self, name, new):
    # This is a static event listener for --> self.volume_inputs <--
    if len(new.added) > 0:
        print "Check it out, we added %s to self.items" % new.added
    elif len(new.removed) > 0:
        print "Check it out, we removed %s from self.items" % new.removed

无论哪种方式,当我运行代码时,我都会得到预期的输出:

[mpenning@Bucksnort ~]$ python spinaltap.py
    - --> Firing _volume_inputs_items_changed() <-- check it out!!
- INITIAL_VALUE var volume_inputs = [5.0]
- APPEND a new volume of 4.0
    - volume_inputs = [5.0] # BEGIN
    - volume_inputs.append(4.0)
    - --> Firing _volume_inputs_items_changed() <-- check it out!!
    - volume_inputs: [5.0, 4.0] # END
    - Test PASSED: Traits fired _volume_inputs_changed()
- NEGATIVE Test... try to append 12.0.  This should fail; 12.0 is out of bounds
    - volume_inputs: [5.0, 4.0] # BEGIN
    - volume_inputs.append(12.0)
    - TraitError raised --> HERE <--
    - volume_inputs: [5.0, 4.0] # END
    - Test PASSED: traits correctly raised TraitError instead of appending 12.0.
[mpenning@Bucksnort ~]$

关于python - 如何在列表上触发 Traits 静态事件通知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8371980/

相关文章:

rust - rust 中是否可能存在具有大小特征的多态性

javascript - 附加节点不会触发 JavaScript 事件

struct - 如何将特征泛型类型链接到已实现类型中的其他元素

python - 创建弹性伸缩组时如何禁用生命周期钩子(Hook)?

python - 我如何告诉 Python sys.argv 在 Unicode 中?

c# - 如何在 VB6 中订阅实例对象的事件?

c# - 为什么我的 C# Remoting 对象超时,即使 Lifetime 返回 null?

rust - 为什么Rust阻止为外部结构实现外部特征?

python - OpenCV/ python : multi-threading for live facial recognition

python - 随机森林准确率太低