覆盖Python中的默认参数

news/2024/7/10 1:31:14 标签: python, java, vue, tensorflow, php

Sometimes you want to change the behavior of a function call in a Python test. Let’s assume you have the following code:

有时您想要更改Python测试中函数调用的行为。 假设您有以下代码:

# a.py

# a.py

from from b b import import subfunc

subfunc

def def funcfunc ():
    ():
    # do something
    # do something
    subfuncsubfunc (( 11 , , 22 )
    )
    # do something else


# do something else


# b.py

# b.py

def def subfuncsubfunc (( aa , , bb == 11 ):
    ):
    # step1
    # step1
    # step2
    # step2
    # step3
# step3

You are testing the func function and would to change the behavior of step2 in subfunc without affecting step1 or step3.

您正在测试func函数,并且将在不影响step1或step3的情况下更改subfunc中step2的行为。

模拟:替换功能 (Mocking: Replacement Function)

One way to solve this would be to mock the entire subfunc:

解决此问题的一种方法是模拟整个子功能

(Note, all example code assumes that you’re using pytest with the monkeypatch fixture. But you can also use other testing frameworks and the mock library instead.)

(请注意,所有示例代码均假定您将pytest与Monkeypatch固定装置一起使用。但是您也可以使用其他测试框架和模拟库。)

But that would require you to copy the body of the function and adjust it as desired. This violates the DRY principle and could be a source of bugs (e.g. if step1 and step3 change later on).

但这将需要您复制函数的主体并根据需要进行调整。 这违反了DRY原理,并且可能是错误的来源(例如,如果稍后更改了步骤1和步骤3)。

依赖注入 (Dependency Injection)

A cleaner way to make the subfunc more dynamic is dependency injection. We simply add a new argument with a default value, and act depending on that value:

使子函数更具动态性的一种更干净的方法是依赖项注入。 我们只需添加一个带有默认值的新参数,然后根据该值执行操作:

# b.py

# b.py

def def subfuncsubfunc (( aa , , bb == 11 , , do_step2do_step2 == TrueTrue ):
    ):
    # step1
    # step1
    if if do_step2 do_step2 is is TrueTrue :
        :
        # step2
    # step2
    # step3
# step3

Now we can simply manipulate the value of the do_step parameter to change the behavior. But how do we actually do that? Two methods come to mind:

现在,我们可以简单地操纵do_step参数的值来更改行为。 但是,我们实际上该如何做呢? 我想到两种方法:

猴子补丁__defaults__ (Monkey patching __defaults__)

Every Python function with default arguments has a __defaults__ attribute. It contains a tuple with all default argument values:

每个带有默认参数的Python函数都具有__defaults__属性。 它包含具有所有默认参数值的元组:

We can manipulate that attribute to change the defaults:

我们可以操纵该属性来更改默认值:

def def test_functest_func (( monkeypatchmonkeypatch ):

    ):

    monkeypatchmonkeypatch .. setattrsetattr (( 'b.subfunc.__defaults__''b.subfunc.__defaults__' , , (( 11 , , FalseFalse ))

    ))

    # do testing of func()
# do testing of func()

This works nicely, there are two downsides though. First of all, it’s hacky due to the use of double underscore methods. But even worse, we have to specify the default argument for the first kwarg too! That violates the DRY principle and could be a source of bugs. Sounds familiar, right?

这很好,但是有两个缺点。 首先,由于使用了双下划线方法,因此很容易出错。 但更糟糕的是,我们也必须为第一个kwarg指定默认参数! 这违反了DRY原则,并且可能是错误的来源。 听起来很熟悉,对吧?

Of course, we could try to retrieve the initial defaults, manipulate them and then monkey patch the __defaults__ attribute again. But that’s even more hacky…

当然,我们可以尝试检索初始默认值,对其进行操作,然后再次用猴子修补__defaults__属性。 但这甚至更hacky…

使用偏函数 (Using a partial function)

A much nicer way is to use partial function application. It’s a method mainly coming from functional programming. You can use it to override the value of some arguments and/or keyword arguments, yielding a higher order function.

一种更好的方法是使用部分函数应用程序。 这是一种主要来自函数式编程的方法。 您可以使用它来覆盖某些自变量和/或关键字自变量的值,从而产生更高阶的函数。

As a short example, let’s create a function that adds 2 to an input value:

举一个简短的例子,让我们创建一个将输入值加2的函数:

Now that you know how partial functions work, let’s use them to override the default argument of our subfunc:

现在您知道了部分函数的工作原理,让我们使用它们来覆盖subfunc的默认参数:

from from functools functools import import partial

partial

def def test_functest_func (( monkeypatchmonkeypatch ):

    ):

    from from b b import import subfunc
    subfunc
    monkeypatchmonkeypatch .. setattrsetattr (( 'b.subfunc''b.subfunc' , , partialpartial (( subfuncsubfunc , , do_step2do_step2 == FalseFalse ))

    ))

    # do testing of func()
# do testing of func()

Now we have a clean way to modify function behavior from tests through dependency injection, without having to resort to Python internals hackery 🙂

现在,我们有了一种干净的方法,可以通过依赖注入来从测试中修改函数行为,而不必求助于Python内部黑客。

翻译自: https://www.pybloggers.com/2016/02/overriding-default-arguments-in-python/


http://www.niftyadmin.cn/n/984678.html

相关文章

repeater绑定泛型liststring

菜鸟D重出江湖&#xff0c;依然是菜鸟&#xff0c;囧&#xff01;言归正传—— 工作中遇到一个repeater绑定的问题&#xff0c;数据源是一个list<string> 集合&#xff0c;然后在界面上使用<%#Eval()%>绑定。问题来了&#xff0c;Eval该绑定那个属性名&#xff08;…

小波去噪为什么要用这个作为阈值,原理是什么 threshold=mad(data)* np.sqrt(2*np.log(len(data)))...

小波去噪是一种信号处理技术&#xff0c;用于在保留信号的基本特征的同时去除噪声。在小波去噪中&#xff0c;阈值是用来决定哪些小波系数应该被保留&#xff0c;哪些应该被删除的重要参数。 公式 threshold mad(data) * sqrt(2 * log(len(data))) 中&#xff0c;mad(data) 是…

水果网上销售平台_新闻和完美的推销平台

水果网上销售平台Having been pretty immersed in the VC funded startup experience at Predikto for a couple of years now, I have (counter to what I would have ever thought), taken an intellectual curiosity to pitch decks. As I come across them, I put up nota…

Supporting Python 3(支持python3)——使用现代的风格改善你的代码

2019独角兽企业重金招聘Python工程师标准>>> 使用现代风格改善你的代码 原文&#xff1a; http://python3porting.com/improving.html 译者&#xff1a; TheLover_Z 一旦你开始使用 Python 3&#xff0c;你就有机会接触新的特性来改善你的代码。这篇文章中提到的很多…

WPF 3D:简单的Point3D和Vector3D动画创造一个旋转的正方体

WPF 3D&#xff1a;简单的Point3D和Vector3D动画创造一个旋转的正方体 原文:WPF 3D&#xff1a;简单的Point3D和Vector3D动画创造一个旋转的正方体 运行结果&#xff1a; 事实上很简单&#xff0c;定义好一个正方体&#xff0c;处理好纹理。关于MeshGeometry3D的正确定义和纹理…

STM32定时器时间计算

STM32定时器可以使用内部时钟或外部时钟来进行时间计算。可以使用不同的计数模式(如自动重装计数器、预装载寄存器等)来满足不同的需求。STM32还提供了多种中断源&#xff0c;可以在计数器溢出或比较匹配时触发中断&#xff0c;从而实现计时和计数功能。

如何用springboot和RabbitMQ实现发送通知给用户的功能,可以给出示例代码吗

首先&#xff0c;你需要在 Spring Boot 项目中添加 RabbitMQ 的依赖。在 pom.xml 文件中添加如下依赖: <dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit</artifactId><version>2.2.2.RELEASE</vers…

(010)XHTML文档之pre标签

XHTML文档之pre标签 在浏览器呈现文档的时候&#xff0c;其中的空白会发生“缩合”&#xff0c;连续的多个空格会被缩减为1个&#xff0c;回车会被忽略。但是&#xff0c;你可以用pre元素定义一段预先格式化过的文本&#xff0c;使其中的空白和换行得以按其在标记代码中的原样保…