2

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

我读过鸭子编程背后的理论。我还读到单元测试(可取并用于静态类型编程)成为缺少编译时检查的动态语言的需要。

但是,我仍然害怕错过大局。特别是,如何检查变量类型意外更改的错误?

让我们用 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 包装吗?

4

1 回答 1

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上述内容更通用,以便您的类可以继承它。

另一个(可能更好的)解决方案(在此处指出)可能是使用Entought Traits

于 2013-06-11T12:04:39.917 回答