Python中的虚拟对象
在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 对象通常在单元测试中使用,所以你可以做的事情远不止我在这里展示的。如果你感兴趣,可以在 这里 阅读更多内容。