微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

调用随机方法时,MagicMock如何避免抛出AttributeError?

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__.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐