所以我在审核代码时遇到了这个有趣的问题:
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(...)
?
答案 0 :(得分:2)
除非更改为
,否则最后一行将引发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
应仅用于检查内部逻辑,而不是用于受代码用户影响的运行时条件。用户可以删除或禁用断言,因此代码在释放后不应依赖于assert的正确操作。
在上面的代码中,__init__
将self.foo_doo
设置为某些内容,但调用者可以随后删除该属性。因此,属性的存在和值都是用户确定的运行时条件,而不是断言的适当主体。
TestCase.assertXxx
的{{1}}方法仅用于测试,当它们失败时,它们不仅仅包装一个简单的unittest
。