在Python中,如果调用不存在的方法,则会抛出AttributeError.防爆
>>> class A:
... def yo(self):
... print(1)
...
>>> a = A()
>>> a.yo()
1
>>> a.hello()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'hello'
在下面的代码中,MagicMock类没有名为hello的函数,或者未为方法hello创建任何补丁.仍然在下面的代码不会引发AttributeError
>>> from unittest.mock import MagicMock
>>> obj = MagicMock()
>>> obj.hello()
<MagicMock name='mock.hello()' id='4408758568'>
MagicMock如何做到这一点?当调用任何方法(可能未定义)时,如何创建可以执行操作的类?
解决方法:
Python数据模型记录了一个钩__getattr__
,当属性访问无法以通常的方式解析时,将调用该钩.模仿者使用它来返回新的模仿实例-即模仿将未知属性定义为factories.
以更简单的方式重现模拟的实现,您只需将__getattr__和__call__转换为工厂函数:
class M:
def __call__(self):
return M()
def __getattr__(self, name):
return M()
用法示例:
>>> mock = M()
>>> mock.potato
<__main__.M at 0xdeadbeef>
>>> mock.potato()
<__main__.M at 0xcafef00d>
How is MagicMock able to do this?
这部分不是特定于MagicMock的,普通的Mock也会做同样的事情(名称中的“魔术”只是指允许更好地模拟magic methods的其他功能). MagicMock inherits such behavior from one of the base classes:
>>> MagicMock.mro()
[unittest.mock.MagicMock,
unittest.mock.MagicMixin,
unittest.mock.Mock,
unittest.mock.CallableMixin,
unittest.mock.NonCallableMock, # <--- this one overrides __getattr__!
unittest.mock.Base,
object]
How can I create a class that can perform an action when any method (which might not be defined) is called on it?
这取决于您要在普通属性访问之前还是之后.如果要排在最前面,则应定义__getattribute__
,在搜索类/实例名称空间之前,将无条件调用它来实现属性访问.但是,如果您要优先考虑普通属性(即那些生活在对象__dict__中的属性)和descriptors,那么您应该按照前面的讨论定义__getattr__.
原文地址:https://codeday.me/bug/20191108/2008186.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。