我可以将python函数的(未赋值)参数转换为字符串吗?

2024-03-28 10:36:16 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中是否可能有一个函数,其中fun(1+1)作为'1+1'而不是2到达函数中

常识会说这是不可能的,因为在将1+1传递给函数之前,无法阻止对其进行求值。 但同样的常识是,下面的PHP代码不应该工作,因为unset($arr[0])应该与unset(99)相同。但它是有效的——后者是一个语法错误

$arr = [99, 1, 2, 3, 99];
unset($arr[0]);  # remove the first element
$arr = array_values($arr);  # reindex from 0
echo $arr == [1, 2, 3, 99];  # yes

所以也许Python也有一个漏洞来解决这种奇怪的问题

我想用它来编写更短的测试。目前我有:

with pytest.raises(ZeroDivisionError):
    1/0
with pytest.raises(ZeroDivisionError):
    0/0
with pytest.raises(ZeroDivisionError):
    0**-1

with pytest.raises(FooError):
    Foo(round_hole=SquarePeg)
with pytest.raises(FooError):
    Foo(give_me_five=6)

相反,我宁愿写:

shorter(ZeroDivisionError, [1/0, 0/0, 0**-1])

shorter(FooError, [
    Foo(round_hole=SquarePeg),
    Foo(give_me_five=6)
])

我当然可以传递字符串,但丢失语法高亮显示的缺点会削弱简洁性的优势

编辑1:通过如下字符串替换将测试文件从测试模式“打开”到写入模式可能不是一个糟糕的主意 ', # expr\n ''", # expr\n "'

# write mode
shorter(FooError, [  # except
    Foo(round_hole=SquarePeg),  # expr
    Foo(give_me_five=6)  # expr
])

# test mode
shorter(FooError, [  # except
    "Foo(round_hole=SquarePeg)",  # expr
    "Foo(give_me_five=6)"  # expr
])

编辑2:事实上,霍夫林提出的lambda方法效果很好。通常情况下,缺少参数会在测试文件中引发错误。避免这种情况的方法是使用__init__(self, arg=None)而不仅仅是__init__(self, arg)

shorter和示例类的定义:

import pytest
from inspect import isclass


def shorter(expected, values):
    if isclass(expected) and issubclass(expected, Exception):
        for value in values:
            with pytest.raises(expected):
                value()
    else:
        for value in values:
            assert value == expected


class Hand():
    def __init__(self, give_me_five=None):
        if give_me_five is None:
            raise NoArgError
        if give_me_five != 5:
            raise NotFiveError
        self.twice_five = 2 * give_me_five


class NoArgError(ValueError):
    """You need to provide and argument."""


class NotFiveError(ValueError):
    """The argument must be 5."""

示例测试文件:

from .other_file import shorter, Hand, NoArgError, NotFiveError


def test_errors():
    check(NoArgError, [
        lambda: Hand()
    ])
    check(NotFiveError, [
        lambda: Hand(0),
        lambda: Hand(6),
        lambda: Hand(''),
        lambda: Hand('5')
    ])


def test_values():
    check(10, [
        Hand(5).twice_five
    ])

Tags: lambdafoopytestwithmeexpectedvaluesshorter
1条回答
网友
1楼 · 发布于 2024-03-28 10:36:16

不可能。这不是R;函数参数在函数有机会执行任何操作之前进行求值

您应该只使用pytest.raisesnon-context-manager form

pytest.raises(FooError, Foo, round_hole=SquarePeg)

pytest.raises(ZeroDivisionError, lambda: 1/0)

这表明,当使用提供的参数调用时,提供的callable会引发提供的异常

相关问题 更多 >