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

ck.*_*ck. 3 python

假设我有这样的代码:

foo = fooFactory.create()
Run Code Online (Sandbox Code Playgroud)

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

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


我考虑过以下几种选择.

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

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

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

Chr*_* K. 9

这个怎么样:

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
Run Code Online (Sandbox Code Playgroud)

虚拟对象响应任何无效的属性访问.


Rob*_*obᵩ 8

你要求一个什么都不做的物体.一个例子object正是这样做的.

def create():
    return object()
Run Code Online (Sandbox Code Playgroud)

另一方面,您可能实际上希望它能够做某事.您可能希望它具有执行和返回的方法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)
Run Code Online (Sandbox Code Playgroud)

  • 这不符合问题中的要求:“这个对象应该是完全惰性的 - 无论如何使用它,它都不应该做任何事情*或抛出任何异常*” (2认同)

Rub*_*las 5

前面关于虚拟对象的答案不适用于嵌套属性/方法。这是我的解决方案:

class Dummy:

    def __init__(*args, **kwargs):
        pass

    def __call__(self, *args, **kwargs):
        return self

    def __getattr__(self, *args, **kwargs):
        return self
Run Code Online (Sandbox Code Playgroud)

现在我们可以访问嵌套的属性和方法:

>>> 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>
Run Code Online (Sandbox Code Playgroud)