2012-05-28 3 views
1

Так что я наткнулся на эту интересную проблему при рассмотрении кода:утверждают, функция упаковщик

class Foo: 

    def __init__(self, foo_name): 
    self.foo_doo = getattr(foo_name, 'foo_lists', None) 

    def assert_foo(self, varname): 
    assert hasattr(self, 'foo_%s' % varname) 

    def foobar(self): 
    assert_foo('doo') 

Wonder, если упаковка утверждают в настроенную версию самостоятельно работает быстрее/лучше решение, то с помощью assert hasattr(...) каждый раз вам нужно, чтобы убедиться, атрибут присутствует, а не None?

+1

Нет особых причин, по которым вы не можете - 'unittest' имеет несколько оберток, таких как' assertEqual'. Это зависит от того, что делает ваш код наиболее читаемым. –

+2

Быстрее? Быстрее набрать, конечно. Очевидно, что медленнее выполнять, так как есть дополнительный вызов функции. – kindall

+3

Я согласен с @ThomasK, я не вижу проблем. Что касается скорости, я думаю, что в большинстве случаев это должно быть незначительным (несмотря на теоретическую разницу, отмеченную @kindall), в зависимости от того, как часто вы выполняете этот код. – ubik

ответ

2

Последняя строка поднимет NameError если не был изменен на

self.assert_foo('doo') 

Это в стороне, я не думаю, что assert следует использовать в коде выше или без обертки. Исправленная строка проверяет только, что self имеет .foo_doo, но не то, что это не None.

if self.foo_doo is not None: 

. Как.

Если один хочет сокращенный просмотровой первый чек атрибута, можно написать

def has_foo(self, name): 
    return hasattr(self, 'foo_'+name) 

def foobar(self): 
    if has_foo('doo'): 

Если вы хотите не- None чека, изменить has_foo возвращения к:

return getattr(self, 'foo_'+name, None) is not None 

Помимо этого, следует , assert в производственном коде должен использоваться только для проверки внутренней логики, а не условий выполнения, затронутых пользователями кода. Пользователи могут удалять или отключать утверждения, поэтому код не должен зависеть от assert для его правильной работы после его выпуска.

В приведенном выше коде, __init__ устанавливает self.foo_dooна что-то, но вызывающий абонент может впоследствии удалить атрибут. Таким образом, как существование, так и значение атрибута являются определяемыми пользователем условиями времени выполнения, а не соответствующими субъектами для утверждений.

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

Смежные вопросы