Проверка нежелательного изменения типа в Python

Я занимаюсь программированием статического типа, и мне интересно понять логику программирования динамического типа, чтобы проверить, могут ли языки динамического типа лучше соответствовать моим потребностям.

Я читал о теории программирования уток. Я также читал, что модульное тестирование (желательное и используемое в программировании статического типа) становится необходимостью в динамических языках, где проверки во время компиляции отсутствуют.

Однако я все еще боюсь упустить общую картину. В частности, как проверить, нет ли ошибки при случайном изменении типа переменной?

Давайте сделаем очень простой пример на 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 справляется с подобными ошибками?

Следует ли обернуть код попыткой / уловом?


person Claudio    schedule 11.06.2013    source источник
comment
В вашем примере модульный тест должен выявить вашу ошибку и потерпеть неудачу. Обертывание в try / except не решит вашу проблему, вам не следует использовать такую ​​конструкцию для обнаружения логической ошибки. Исключением является именно то поведение, которое вы хотели бы в этом случае, чтобы вы могли найти и исправить проблему. Поскольку Python имеет динамическую типизацию, вы всегда будете сталкиваться с этой проблемой, но, опять же, модульные тесты должны ее решить.   -  person Blubber    schedule 11.06.2013
comment
Кроме того, это stackoverflow.com/questions/1912476/ только что появилось на боковой панели" Связанные ".   -  person Blubber    schedule 11.06.2013
comment
Я понимаю. Таким образом, модульное тестирование - это правильный способ справиться с подобными проблемами (в данном случае я считаю, что проверки статического типа более надежны). Большое спасибо.   -  person Claudio    schedule 11.06.2013


Ответы (1)


Это не даст вам проверок во время компиляции, но, поскольку вы предложили использовать 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 выше более общим, чтобы ваши классы могли наследовать от него.

Другое (возможно, лучшее) решение (указанное здесь) могло заключаться в использовании Привлеченные черты

person E.Z.    schedule 11.06.2013