Динамическая инициализация объекта Traits Range

У меня возникли проблемы с динамической инициализацией объекта Traits Range.

Следующий код является очень простым примером того, что я пытаюсь сделать, но, к сожалению, терпит неудачу со следующей ошибкой типа:

TypeError: неподдерживаемые типы операндов для -: 'int' и 'code'

from traits.api import HasTraits, Int, Range
from traitsui.api import View, Item

class DynamicRange(HasTraits):
    """Dynamic initialisation of a Range object"""
    N = Int()
    R = Range(low=0, high='N')

    traits_view = View(Item('R'), Item('N'))

    def __init__(self, N):
        self.N = N         # initial parameter value for N

    def _N_default(self):
        return self.N

Robject = DynamicRange(N=10)
Robject.configure_traits()

Код работает, если я заменяю определение «R» на: R = Range(low=0, high=10), но тогда, конечно, я не получаю динамическую инициализацию верхнего предела диапазона. параметр, который я ищу.

Все предложения с благодарностью приняты.

* Изменить после ответа Джонатана *

Вот простое решение моего вопроса с использованием полезного предложения Джонатана ниже:

from traits.api import HasTraits, Range
from traitsui.api import View, Item

class DynamicRange(HasTraits):
    """Dynamic initialisation of a Range object"""
    traits_view = View(Item('R'))

    def __init__(self, N):
        self.add_trait("R", Range(0, N))

Robject = DynamicRange(N=30)
Robject.configure_traits()

person dreme    schedule 09.02.2015    source источник


Ответы (2)


Одним из способов было бы определить черту не обычным способом, а в пределах __init__, таким образом:

    self.add_trait("R", Range(0, N))

См. http://docs.enthought.com/traits/traits_user_manual/advanced.html#per-object-trait-attributes

person Jonathan March    schedule 09.02.2015

Вы столкнулись с ошибкой Traits/TraitsUI:

Обходной путь - создать еще одну черту для нижнего уровня:

from traits.api import HasTraits, Int, Range
from traitsui.api import View, Item


class DynamicRange(HasTraits):
    """Dynamic initialisation of a Range object"""

    # Upper limit of R
    N = Int()

    # Lower limit of R (not exposed to the user)
    _zero = Int(value=0)

    R = Range(low='_zero', high='N')

    traits_view = View(Item('R'), Item('N'))


Robject = DynamicRange(N=10)
Robject.configure_traits()

Или используйте решение @JonathanMarch. :)

person Warren Weckesser    schedule 10.02.2015
comment
Спасибо за объяснение сути этого вопроса, Уоррен. Если вы хотите, чтобы диапазон был действительно динамическим (а не только при инициализации), то это гораздо лучшее решение, как показано в примере кода Уоррена. - person Jonathan March; 12.02.2015
comment
Да, спасибо, Уоррен, это действительно лучшее решение, поскольку оно позволяет обновлять код класса. Я не знал, что трейт-объекты, объявленные в начале кода класса, могут быть инициализированы переданными параметрами при создании объекта. - person dreme; 13.02.2015
comment
Ах, но я вижу, что передача параметров таким образом работает, только если у вас нет функции init в коде вашего класса. - person dreme; 13.02.2015
comment
Я не включил метод __init__(), потому что он не имел отношения к проблеме. Вы можете добавить метод __init__(), но убедитесь, что он включает вызов метода __init__() родительского класса. То есть, если у вас есть, скажем, def __init__(self, **kw): в классе DynamicRange, то включите в метод строку super(DynamicRange, self).__init__(**kw). - person Warren Weckesser; 13.02.2015
comment
@dreme - комментарий Уоррена здесь стоит изучить, чтобы лучше понять, как использовать наследование классов. - person Jonathan March; 15.02.2015
comment
Спасибо за это разъяснение, Уоррен. Я уже видел этот код с оператором super, но не совсем понял, для чего он нужен. - person dreme; 16.02.2015