从类构造函数[Python / Traits]中更改属性参数

时间:2012-03-31 13:11:57

标签: python constructor traits

我是python的新手 - 抱歉,如果我的术语错了。我有一个继承Enthought Traits attributes的类。这是一个简化版本:

from enthought.traits.api import HasTraits, Range
from enthought.traits.ui.api import View, Item

class GUIThing(HasTraits):

    my_slider = Range(0.0, 0.6, 0.1)
    my_slider._high = 0.7   # works; not what I need 'coz not instance-dependent

    view = View( Item('my_slider') )

    def __init__(self, arg1):
        # Call the parent's __init__
        HasTraits.__init__(self)

        self.my_slider._high = arg1  # what I need; doesn't work

# -- Main program -----

top_range = 0.9

my_gui = GUIThing(top_range)
my_gui.configure_traits()

这只会创建一个窗口,其中包含slider,最初从0.0到0.6,初始值为0.1。创建GUIThing实例时,我想根据当前top_range值更改滑块的最大值。但行

self.my_slider._high = arg1

结果

AttributeError: 'float' object has no attribute '_high'

当在__init__()范围内时,self.my_slider不返回滑块对象,而是返回滑块的当前值。

我做错了什么?谢谢!

修改

以下也不起作用:

class GUIThing(HasTraits):

    def __init__(self, arg1):
        # Call the parent's __init__
        HasTraits.__init__(self)

        self.my_slider = Range(0.0, arg1, 0.0)

    view = View( Item('my_slider') )

这将是我正在尝试做的直接方式,但它会导致GUI而不是滑块,有一个文本框,上面写着“enthought.traits.trait_types.Range对象在0xa61946c” 。所以问题是在my_slider内创建__init__()时,“my_slider”意味着对象本身(通过View无法正确显示);但如果在my_slider之外创建__init__(),则“my_slider”将表示当前值(浮点数;这会阻止访问对象属性)。

不确定这是Traits特有的还是我不知道如何正确初始化对象。

5 个答案:

答案 0 :(得分:4)

最后在a recent mailing list message找到答案。

以下代码有效。似乎魔鬼在如何调用Range()的细节中:Range(my_slider_low, my_slider_hi, 0.1) 工作。

from enthought.traits.api import HasTraits, Range
from enthought.traits.ui.api import View, Item

class GUIThing(HasTraits):

    my_slider_low = 0.0
    my_slider_hi = 1.0

    my_slider = Range(low='my_slider_low', high='my_slider_hi', value=0.1)  

    def __init__(self, arg1):
        self.my_slider_hi = arg1 

    view = View( Item('my_slider') )

top_range = 0.2

my_gui = GUIThing(top_range)
my_gui.configure_traits()

答案 1 :(得分:0)

我的内心感觉是你不需要修改那个类,而是扩展Range类并添加处理特定情况所需的额外逻辑。

答案 2 :(得分:0)

您需要使用add_trait方法,该方法可以使用您需要的值动态创建新的Range特征。

这取自Advanced page of the traits user manual

from traits.api import HasTraits, Range

class GUISlider (HasTraits):

def __init__(self, eval=None, label='Value',
             trait=None, min=0.0, max=1.0,
             initial=None, **traits):
    HasTraits.__init__(self, **traits)
    if trait is None:
        if min > max:
            min, max = max, min
        if initial is None:
            initial = min
        elif not (min <= initial <= max):
            initial = [min, max][
                        abs(initial - min) >
                        abs(initial - max)]
        trait = Range(min, max, value = initial)
    self.add_trait(label, trait)

答案 3 :(得分:0)

Pteridium的答案确实存在问题。它确实有效,但违反了两条规则/建议。

首先,您已使用自己的 init 覆盖了构造函数。如果你这样做(如果你可以避免,你不应该根据Traits的编码建议),你应该用类似的东西调用父构造函数 super(GUISlider,self)。 init (self,** kwargs)

其次,HasTraits子元素的推荐初始化是在构造函数的实例化过程中完成的,该构造函数采用关键字参数。在您的情况下,代码可能像

from enthought.traits.api import HasTraits, Range
from enthought.traits.ui.api import View, Item

class GUIThing(HasTraits):

    my_slider_low = 0.0
    my_slider_hi = 1.0

    my_slider = Range(low='my_slider_low', high='my_slider_hi', value=0.1)  

    view = View( Item('my_slider') )


my_gui = GUIThing(my_slider_hi=0.4)
my_gui.configure_traits()

你去,做你想要的(我想),更少的代码,并遵循特征。如果有人能解释为什么我们不应该使用构造函数,我想知道。罗伯特克恩可能会告诉我们。

答案 4 :(得分:0)

我发现了dynamic range from Jonathan March.的一个很好的例子。这给出了OP想要AFAICT的所有行为:

# Imports:
from traits.api import HasPrivateTraits, Float, Range, Int

from traitsui.api import View, Group, Item, Label, RangeEditor

class DynamicRangeEditor ( HasPrivateTraits ):
    """ Defines an editor for dynamic ranges (i.e. ranges whose bounds can be
        changed at run time).
    """

    # The value with the dynamic range:
    value = Float

    # This determines the low end of the range:
    low = Float(0.0)

    # This determines the high end of the range:
    high = Float(50)

    # Traits view definitions:
    traits_view = View(

        # Dynamic simple slider demo:
        Group(
            Item( 'value',
                   editor = RangeEditor( low_name    = 'low',
                                         high_name   = 'high',
                                         format      = '%.1f',
                                         label_width = 28,
                                         mode        = 'auto' )
            ),
            '_',
            Item( 'low' ),
            Item( 'high' ),
            '_',
        ),

        title     = 'Dynamic Range Editor Demonstration',
        buttons   = [ 'OK' ],
        resizable = True
    )


# Create the demo:
demo = DynamicRangeEditor()

# Run the demo (if invoked from the command line):
if __name__ == '__main__':
    demo.configure_traits()