检查Python中不需要的类型更改

时间:2013-06-11 08:16:32

标签: python pylint dynamic-typing pyflakes pychecker

我来自静态类型编程,我有兴趣了解动态类型编程背后的基本原理,以检查动态类型语言是否能更好地满足我的需求。

我读过鸭子编程背后的理论。我还读到,单元测试(在静态类型编程中是可取的和使用的)在动态语言中变得需要,其中缺少编译时检查。

然而,我仍然不敢错过大局。特别是,如何检查变量类型被意外更改的错误?

让我们在Python中做一个非常简单的例子:

#! /usr/bin/env python

userid = 3
defaultname = "foo"

username = raw_input("Enter your name: ")
if username == defaultname:
    # Bug: here we meant userid...
    username = 2

# Here username can be either an int or a string
# depending on the branch taken.
import re
match_string = re.compile("oo")
if (match_string.match(username)):
        print "Match!"

Pylint,pychecker和pyflakes不会就此问题发出警告。

处理这类错误的Pythonic方法是什么?

代码是否应该使用try / catch包装?

1 个答案:

答案 0 :(得分:0)

这不会在编译时给你检查,但正如你建议使用try / catch,我会假设运行时检查也会有所帮助。

如果使用类,可以在__setattr__方法中挂钩自己的类型检查。例如:

import datetime

# ------------------------------------------------------------------------------
# TypedObject
# ------------------------------------------------------------------------------
class TypedObject(object):     
    attr_types = {'id'         : int,
                  'start_time' : datetime.time,
                  'duration'   : float}

    __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            = TypedObject()

>>> my_typed_object.id         = "XYZ"      # ERROR
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        # OK

您可以继续使上面的TypedObject更通用,以便您的类可以继承它。

另一个(可能更好)解决方案(指出here)可能是Entought Traits