【问题标题】:assert wrapper function断言包装函数
【发布时间】:2012-06-03 00:45:25
【问题描述】:

所以我在查看代码时遇到了这个有趣的问题:

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')

想知道是否将断言包装到您自己的自定义版本是更快/更好的解决方案,然后每次需要确保属性存在而不是 None 时使用 assert hasattr(...)

【问题讨论】:

  • 没有什么特别的原因你不能 - unittest 有许多像 assertEqual 这样的包装器。这取决于使您的代码最易读的因素。
  • 更快?当然,打字速度更快。显然,执行速度较慢,因为涉及到一个额外的函数调用。
  • 我同意@ThomasK,我认为没有问题。至于速度,我认为在大多数情况下应该可以忽略不计(尽管@kindall 指出了理论上的差异),具体取决于您执行此代码的频率。

标签: python-3.x python-2.7 python pep8


【解决方案1】:

最后一行将引发NameError,除非更改为

self.assert_foo('doo')

除此之外,我不认为assert 应该在上面的代码中使用或不使用包装器。更正后的行仅检查self 是否设置了.foo_doo,但不是None

if self.foo_doo is not None:

两者都有。

如果你想要一个简短的look-first属性检查,你可以写

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 应仅用于检查内部逻辑,而不应用于检查代码用户影响的运行时条件。用户可以删除或禁用断言,因此代码一旦发布就不应依赖断言来正常运行。

在上面的代码中,__init__self.foo_doo 设置为something,但调用者随后可以删除该属性。因此属性的存在和值都是用户确定的运行时条件,而不是断言的合适主题。

unittestTestCase.assertXxx 方法仅用于测试,当它们失败时,它们所做的不仅仅是包装一个简单的assert

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2021-02-13
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多