Могу ли я передать невычисленное выражение в качестве аргумента функции, а не как строку?Python

Программы на Python
Ответить
Anonymous
 Могу ли я передать невычисленное выражение в качестве аргумента функции, а не как строку?

Сообщение Anonymous »

Возможно ли иметь функцию в 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)
])

Конечно, я мог бы передавать строки, но недостаток утраченной подсветки синтаксиса свел бы на нет преимущество краткости.
Возможно, не такая уж плохая идея «открыть» тестовый файл из тестового режима в режим записи, сделав замену строк, например
', # 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
])

На самом деле лямбда-подход, предложенный Хофлингом, работает нормально. Обычно отсутствие аргументов вызывает ошибку прямо в тестовом файле. Чтобы избежать этого, используйте __init__(self, arg=None) вместо просто __init__(self, arg).
Определение более коротких и примеров классов:
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
])


Подробнее здесь: https://stackoverflow.com/questions/613 ... -as-a-stri
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»