2

在对象中设置属性时进行类型检查的最有效方式是什么(“高效”不一定意味着快速,而是“优雅”“可维护”)?

我可以用它__slots__来定义允许的属性,但是我应该如何限制类型呢?

当然,我可以为每个属性编写“setter”方法,但我发现维护起来有点麻烦,因为我的类型检查通常很简单。

所以我正在做这样的事情:

import datetime

# ------------------------------------------------------------------------------
# MyCustomObject
# ------------------------------------------------------------------------------
class MyCustomObject(object):
    pass

# ------------------------------------------------------------------------------
# MyTypedObject
# ------------------------------------------------------------------------------
class MyTypedObject(object):     
    attr_types = {'id'         : int,
                  'start_time' : datetime.time,
                  'duration'   : float,
                  'reference'  : MyCustomObject,
                  'result'     : bool,
                  'details'    : str}

    __slots__ = attr_types.keys()

    # --------------------------------------------------------------------------
    # __setattr__
    # --------------------------------------------------------------------------
    def __setattr__(self, name, value):
        if name not in self.__slots__:
            raise AttributeError(
                "'%s' object has no attribute '%s'" 
                % (self.__class__.__name__, name))
        if type(value) is not self.attr_types[name]:
                raise TypeError(
                    "'%s' object attribute '%s' must be of type '%s'" 
                    % (self.__class__.__name__, name, 
                       self.attr_types[name].__name__))
        # call __setattr__ on parent class
        super(MyTypedObject, self).__setattr__(name, value)

这对我的目的很好:

>>> my_typed_object            = MyTypedObject()
>>> my_typed_object.id         = "XYZ"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 28, in __setattr__
TypeError: 'MyTypedObject' object attribute 'id' must be of type 'int'
>>> my_typed_object.id         = 123
>>> my_typed_object.reference  = []
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 28, in __setattr__
TypeError: 'MyTypedObject' object attribute 'reference' must be of type 'MyCustomObject'
>>> my_typed_object.reference  = MyCustomObject()
>>> my_typed_object.start_time = "13:45"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 28, in __setattr__
TypeError: 'MyTypedObject' object attribute 'start_time' must be of type 'time'
>>> my_typed_object.start_time = datetime.time(13, 45)

有一个更好的方法吗?使用 Python 已经有一段时间了,我觉得我正在重新发明轮子。

4

2 回答 2

1

你应该问问自己为什么你觉得有必要这样做。它当然不是很 Pythonic。通常在 Python 中,我们不要求属性具有特定的类型:相反,我们记录预期的类型,并假设任何实际参数都符合。请注意,这可能意味着实现相同方法的完全不相关的类型:例如,我们可能期望参数是可迭代的,而不特别要求它从列表或元组继承。

于 2012-11-19T15:06:19.833 回答
1

一个已经实现了您正在寻找的东西(并提供了许多其他功能)的库是Enthought Traits

于 2012-11-21T13:11:12.133 回答