假设我有这样的代码:
foo = fooFactory.create()
由于各种原因,fooFactory.create()
可能无法创建Foo
的实例。
如果是,我希望fooFactory.create()
返回一个虚拟/无操作对象。这个对象应该是完全惰性的 - 无论它如何使用,它都不应该做任何事情或抛出任何异常。请注意,foo
没有返回值的方法。
我考虑过以下选项。
首先,创建一个模拟。这样做的好处是它很容易并且完全符合我的要求。缺点是在生产代码中使用模拟会感觉很奇怪。更重要的是,我无法控制模拟库,因此它的行为可能会在某些时候发生变化并破坏我的应用程序。
其次,创建一个虚拟 NoopFoo
/ DummyFoo
类。然后我手动实现它需要支持的方法,并将pass
放在方法体中。我知道它的优点永远不会破坏我的应用程序。缺点是,如果将来使用Foo
的其他方法,我必须知道更新NoopFoo
/ DummyFoo
...或者我的申请可能会中断。
有比这些更好的选择吗?请注意,我是Python的新手,所以如果它涉及更高级的Python功能,我会感激更多的信息。谢谢!
答案 0 :(得分:8)
这个怎么样:
class MayBeCalled(object):
def __call__(self, *args, **kwargs):
return None
class Dummy(object):
def __getattr__(self, attr):
return MayBeCalled()
def __setattr__(self, attr, val):
pass
a = Dummy()
print a.nn
<__main__.MayBeCalled object at 0x103ca9a90>
print a.nn()
None
a.nn = 23
print a.nn()
None
Dummy对象响应任何无效的属性访问。
答案 1 :(得分:7)
你要求一个什么都不做的物体。 object
的一个实例恰恰就是这样。
def create():
return object()
另一方面,您可能实际上希望它能够做某事。您可能希望它具有执行并返回None
的方法。您可能会返回此类的实例:
In [1]: class Nop(object):
...: def nop(*args, **kw): pass
...: def __getattr__(self, _): return self.nop
...:
In [2]: n=Nop()
In [3]: n.foo
Out[3]: <bound method Nop.nop of <__main__.Nop object at 0x7f9fec034650>>
In [4]: n.foo()
In [5]: n.foo(1,2,3)
答案 2 :(得分:3)
以前关于虚拟对象的答案不适用于嵌套的属性/方法。这是我的解决方案:
class Dummy:
def __init__(*args, **kwargs):
pass
def __call__(self, *args, **kwargs):
return self
def __getattr__(self, *args, **kwargs):
return self
现在我们可以访问嵌套的属性和方法:
>>> d = Dummy()
>>> d.my_attr
<__main__.Dummy object at 0x10d007160>
>>> d.my_method()
<__main__.Dummy object at 0x10d007160>
>>> d.my_attr.my_method()
<__main__.Dummy object at 0x10d007160>
>>> d.my_attr.my_other_attr
<__main__.Dummy object at 0x10d007160>
答案 3 :(得分:1)
考虑nop
包,可通过pip install nop
获取。请不要使用mock
包(测试除外),因为它存储了通话记录!
from nop import NOP
dummy = NOP()
dummy.foo()
NOP
dummy.foo().bar()
NOP
dummy.foo('x', 'y')
NOP
dummy.foo('x', 'y', z=3)
NOP
type(_)
<class 'nop.nop_base.NOP'>
其源代码为here。
答案 4 :(得分:-1)
class Dummy(object):
pass
a = Dummy()
# want to add a method?
a.something = lambda self: "hi"
print a.something()