如何在特征中指定特定类型的可变长度元组?
How to specify variable-length tuple of specific type in traits?
from traits.api import HasTraits, Str, Tuple
class Data(HasTraits):
values = Tuple(Str, ...)
data = Data(values=("a", "b", "c"))
输出:
TraitError: The 'values' trait of a Data instance must be a tuple of the form: (a string, an ellipsis or None), but a value of ('a', 'b', 'c') <class 'tuple'> was specified.
我正在学习 traits api 并阅读了文档,但我没有找到将任何特定类型传递给 traits 中的可变长度元组的方法。我收到错误!我该如何解决?
已将 values = Tuple(Str, ...)
更改为 values = Tuple(Str)
,仍然得到:
TraitError: The 'values' trait of a Data instance must be a tuple of the form: (a string), but a value of ('a', 'b', 'c') <class 'tuple'> was specified.
虽然我的 Traits-fu 已今非昔比,但我可以尝试一下。
您希望 Traits 能够像验证 List
特征一样验证 Tuple
特征,不幸的是,这就是问题所在。 Tuples
的内容未经验证。我 认为 这是因为 List
是可变的而 Tuple
是不可变的,所以期望 List
的值会改变(因此需要验证)并且 Tuple
的值不会,因此 Tuple
特征不承担验证机制的权重。
考虑到这一点,指定 values = Tuple(Str, ...)
并不代表您根据 list_values = List(Str)
的行为所认为的含义。
考虑这两个 类:
from traits.api import HasTraits, List, Str, Tuple
class Foo(HasTraits):
t_values = Tuple(Str)
class Bar(HasTraits):
l_values = List(Str)
f = Foo(t_values=(1,2,3))
b = Bar(l_values=[1,2,3])
它们都应该触发验证错误。请注意每个错误的差异:
TraitError: The 't_values' trait of a Foo instance must be a tuple of the form: (a string), but a value of (1, 2, 3) <class 'tuple'> was specified.
Traits 期望 t_values
是“以下形式的元组:(字符串)”
TraitError: Each element of the 'l_values' trait of a Bar instance must be a string, but a value of 1 <class 'int'> was specified.
这是您在指定错误类型时预期的正常验证错误。
根据 Tuple docs,可变长度元组不是一个选项:
The default value is determined as follows:
- If no arguments are specified, the default value is ().
- If a tuple is specified as the first argument, it is the default value.
- If a tuple is not specified as the first argument, the default value is a tuple whose length is the length of the argument list, and whose values are the default values for the corresponding trait types.
您描述的用例,单一类型的 variable-length 序列是您使用 List(Str)
得到的结果,尽管您没有获得不变性。您可以通过创建一个获取和设置元组但在封面下存储列表的 属性 来伪造它:
from traits.api import HasTraits, List, Str, Tuple, Property
class Foo(HasTraits):
t_prop = Property(Tuple)
_data = List(Str)
def _get_t_prop(self):
return tuple(self._data)
def _set_t_prop(self, value):
self._data = list(value)
foo = Foo()
foo.t_prop = ('a',)
print(foo.t_prop)
foo.t_prop = ('a', 'b')
print(foo.t_prop)
foo.t_prop = ('a', 'b', 1)
print(foo.t_prop)
这将产生以下输出。这不太正确,因为错误消息是由列表验证器触发的,而不是元组的。
('a',)
('a', 'b')
Traceback (most recent call last):
...
traits.trait_errors.TraitError: Each element of the '_data' trait of a Foo instance must be a string, but a value of 1 <class 'int'> was specified.
您可以使用类似以下内容验证 Tuple 类型,但这开始感觉有点恶心:
def _set_t_prop(self, value):
validator = Tuple((Str, ) * len(value))
validator.validate(self, "t_prop", value)
self._data = list(value)
生成的输出是:
('a',)
('a', 'b')
traits.trait_errors.TraitError: The 't_prop' trait of a Foo instance must be a tuple of the form: (a string, a string, a string), but a value of ('a', 'b', 1) <class 'tuple'> was specified.
from traits.api import HasTraits, Str, Tuple
class Data(HasTraits):
values = Tuple(Str, ...)
data = Data(values=("a", "b", "c"))
输出:
TraitError: The 'values' trait of a Data instance must be a tuple of the form: (a string, an ellipsis or None), but a value of ('a', 'b', 'c') <class 'tuple'> was specified.
我正在学习 traits api 并阅读了文档,但我没有找到将任何特定类型传递给 traits 中的可变长度元组的方法。我收到错误!我该如何解决?
已将 values = Tuple(Str, ...)
更改为 values = Tuple(Str)
,仍然得到:
TraitError: The 'values' trait of a Data instance must be a tuple of the form: (a string), but a value of ('a', 'b', 'c') <class 'tuple'> was specified.
虽然我的 Traits-fu 已今非昔比,但我可以尝试一下。
您希望 Traits 能够像验证 List
特征一样验证 Tuple
特征,不幸的是,这就是问题所在。 Tuples
的内容未经验证。我 认为 这是因为 List
是可变的而 Tuple
是不可变的,所以期望 List
的值会改变(因此需要验证)并且 Tuple
的值不会,因此 Tuple
特征不承担验证机制的权重。
考虑到这一点,指定 values = Tuple(Str, ...)
并不代表您根据 list_values = List(Str)
的行为所认为的含义。
考虑这两个 类:
from traits.api import HasTraits, List, Str, Tuple
class Foo(HasTraits):
t_values = Tuple(Str)
class Bar(HasTraits):
l_values = List(Str)
f = Foo(t_values=(1,2,3))
b = Bar(l_values=[1,2,3])
它们都应该触发验证错误。请注意每个错误的差异:
TraitError: The 't_values' trait of a Foo instance must be a tuple of the form: (a string), but a value of (1, 2, 3) <class 'tuple'> was specified.
Traits 期望 t_values
是“以下形式的元组:(字符串)”
TraitError: Each element of the 'l_values' trait of a Bar instance must be a string, but a value of 1 <class 'int'> was specified.
这是您在指定错误类型时预期的正常验证错误。
根据 Tuple docs,可变长度元组不是一个选项:
The default value is determined as follows:
- If no arguments are specified, the default value is ().
- If a tuple is specified as the first argument, it is the default value.
- If a tuple is not specified as the first argument, the default value is a tuple whose length is the length of the argument list, and whose values are the default values for the corresponding trait types.
您描述的用例,单一类型的 variable-length 序列是您使用 List(Str)
得到的结果,尽管您没有获得不变性。您可以通过创建一个获取和设置元组但在封面下存储列表的 属性 来伪造它:
from traits.api import HasTraits, List, Str, Tuple, Property
class Foo(HasTraits):
t_prop = Property(Tuple)
_data = List(Str)
def _get_t_prop(self):
return tuple(self._data)
def _set_t_prop(self, value):
self._data = list(value)
foo = Foo()
foo.t_prop = ('a',)
print(foo.t_prop)
foo.t_prop = ('a', 'b')
print(foo.t_prop)
foo.t_prop = ('a', 'b', 1)
print(foo.t_prop)
这将产生以下输出。这不太正确,因为错误消息是由列表验证器触发的,而不是元组的。
('a',)
('a', 'b')
Traceback (most recent call last):
...
traits.trait_errors.TraitError: Each element of the '_data' trait of a Foo instance must be a string, but a value of 1 <class 'int'> was specified.
您可以使用类似以下内容验证 Tuple 类型,但这开始感觉有点恶心:
def _set_t_prop(self, value):
validator = Tuple((Str, ) * len(value))
validator.validate(self, "t_prop", value)
self._data = list(value)
生成的输出是:
('a',)
('a', 'b')
traits.trait_errors.TraitError: The 't_prop' trait of a Foo instance must be a tuple of the form: (a string, a string, a string), but a value of ('a', 'b', 1) <class 'tuple'> was specified.