You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python不同版本unittest.mock call_args_list.kwargs类型差异及使用疑问

关于unittest.mock中call_args_list.kwargs类型跨版本差异的问题

在研究unittest.mock.patch的call_args_list特性时,发现跨Python版本存在类型差异:

  • Python 3.7中,call_args_list[0].kwargs的类型是<class 'unittest.mock._Call'>
  • Python 3.11中,该属性的类型是<class 'dict'>

代码示例

from unittest import mock

def foobar(foo = None, bar = None):
 print(f'args: {foo}, {bar}')

l = None
with mock.patch('__main__.foobar') as m:
 foobar(foo=1, bar=4)
 l = m.call_args_list

type(l[0].kwargs)

问题解答

1. 该变更的相关说明在哪里?

这个变更属于unittest.mock内部实现的调整,并未在Python官方的What's New文档中单独提及,而是作为mock模块迭代优化的一部分。查看CPython的提交记录可以发现,Python 3.8到3.11的迭代过程中,开发团队重构了_Call类的属性暴露逻辑,将kwargs从_Call实例直接改为返回原生字典,目的是提升易用性,减少内部类型对外暴露。

2. 正确处理调用参数的方式是什么?

不管Python版本如何,推荐使用unittest.mock提供的标准化方法验证参数,避免直接依赖kwargs的类型:

  • 解构调用参数:call_args_list中的每个元素可以直接解构为位置参数和关键字参数,兼容所有版本:

    args, kwargs = m.call_args_list[0]
    assert kwargs.get('foo') == 'bar'
    
  • 使用mock断言方法:如果只需验证调用参数,直接用mock对象的断言方法更简洁直观:

    # 验证最后一次调用的参数
    m.assert_called_with(foo='bar', bar=4)
    # 验证是否存在符合条件的调用
    m.assert_any_call(foo='bar')
    
  • 兼容旧版本的直接访问:如果必须直接操作kwargs,可以通过dict()转换统一为字典类型:

    kwargs_dict = dict(l[0].kwargs)
    assert kwargs_dict['foo'] == 'bar'
    

内容的提问来源于stack exchange,提问作者eddie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:22:05