Python中的虚拟对象

4 投票
2 回答
4617 浏览
提问于 2025-04-17 20:20

在Python中,能不能创建一个“傻傻的”虚拟对象,这个对象无论怎么调用或者操作,都会什么都不做,也不会报错呢?

这种对象的用途是,当在正常情况下使用这个对象时,它会产生一些副作用,但如果在不同的环境中运行(比如说,在开发阶段),它就不应该做任何事情,也不会出错。

try:
    o = Obj()
except ImportError:
    # we're in development mode
    o = DummyObj()

o.doStuff()  # should work or fail silently

2 个回答

0

我知道我来得有点晚了……但关于“有没有更简单的方法来完成这个,而不使用mock?”,我最近也遇到过同样的问题:这个对象会对很多事情很有抵抗力,它很小,并且不依赖其他东西。这是一种“空对象设计模式”。

class Dummy():
    '''
    Dummy that can be called and is also a context manager.
    It will always return itself, so that you can chain calls.
    '''
    # Accessing attributes
    def __getattr__(self, name):
        return self
    # Callable
    def __call__(self, *args, **kwargs):
        return self
    # Context manager
    def __enter__(self):
        return self
    def __exit__(self, *args, **kwargs):
        pass
    # Indexing, Subscripting, Slicing
    def __getitem__(self, *args, **kwargs):
        return self
    def __setitem__(self, key, value):
        self
    # String representation
    def __str__(self) -> str:
        return '<Just a Dummy>'

比如说,它可以这样使用:

logger = Dummy()
logger.info('Black hole for logging', stacklevel=1)

open = Dummy()
with open("file.txt", "r") as f: # fake context manager
    print(f.read()) # <Just a Dummy>

mlflow = Dummy()
with mlflow.start_run(): # chaining works also
    mlflow.log_param("param1", 5)
    mlflow.a.b().c.d() # multiple chaining

# indexing and subscripting
df = Dummy()
df['col']
df[7]
df.iloc[2:42, ['col1', 'col2']]

当然,它不会返回有意义的值,这需要为每个属性或函数单独实现,比如:

    def get_count(self):
        return 0

欢迎大家提出改进建议。

9

试着使用 Mock 对象。对 Mock 对象的任何调用都会返回另一个 Mock 对象。

举个例子:

>>> from mock import Mock
>>> test = Mock()
>>> test.doStuff()
<Mock name='mock.doStuff()' id='4373729360'>
>>> test2 = test.doStuff
>>> test2
<Mock name='mock.doStuff' id='4373693712'>
>>> test2()
<Mock name='mock.doStuff()' id='4373729360'>

如这里所示,它是很一致的——多次调用 doStuff() 会返回相同的 Mock,而如果你调用由 mock.doStuff 创建的 Mock,它也会返回与 doStuff() 相同的 Mock

Mock 对象通常在单元测试中使用,所以你可以做的事情远不止我在这里展示的。如果你感兴趣,可以在 这里 阅读更多内容。

撰写回答