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

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

4

1 回答 1

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

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

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

于 2012-05-28T23:50:34.223 回答