在Python中编写一个no-op或dummy类

时间:2014-07-25 00:47:48

标签: python

假设我有这样的代码:

foo = fooFactory.create()

由于各种原因,fooFactory.create()可能无法创建Foo的实例。

如果是,我希望fooFactory.create()返回一个虚拟/无操作对象。这个对象应该是完全惰性的 - 无论它如何使用,它都不应该做任何事情或抛出任何异常。请注意,foo没有返回值的方法。


我考虑过以下选项。

首先,创建一个模拟。这样做的好处是它很容易并且完全符合我的要求。缺点是在生产代码中使用模拟会感觉很奇怪。更重要的是,我无法控制模拟库,因此它的行为可能会在某些时候发生变化并破坏我的应用程序。

其次,创建一个虚拟 NoopFoo / DummyFoo类。然后我手动实现它需要支持的方法,并将pass放在方法体中。我知道它的优点永远不会破坏我的应用程序。缺点是,如果将来使用Foo的其他方法,我必须知道更新NoopFoo / DummyFoo ...或者我的申请可能会中断。

有比这些更好的选择吗?请注意,我是Python的新手,所以如果它涉及更高级的Python功能,我会感激更多的信息。谢谢!

5 个答案:

答案 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()