Попробуйте python кроме как функцию для оценки выражений

Я попытался создать функцию, которая пытается выражение и возвращает ноль, если возникли ошибки.

def try_or_zero(exp):
    try:
        exp
        return exp
    except:
        return 0

Что, очевидно, не работает. Кажется, проблема в том, что у python нет никакой формы отложенной оценки, поэтому выражение вычисляется до того, как оно передается в функцию, и поэтому оно вызывает ошибку, прежде чем попадает в функцию и поэтому никогда не проходит через логику попытки. Кто-нибудь знает, можно ли это сделать в Python? ура

5 ответов

Кажется, проблема в том, что у python нет ленивых вычислений

Эээ... да, но возможно не в той форме, которую вы ожидаете. Аргументы функции действительно перед вычислением передаются функции eval'd, поэтому

try_or_zero(foo.bar())

будет действительно выполнен как:

param = foo.bar()
try_or_zero(param)

Теперь функции Python являются простыми объектами (их можно использовать как переменные, передавать в качестве аргументов функций и т. Д.), И они вызываются только при применении оператора вызова (парены, с аргументами или без них), поэтому вы можете передать функцию try_or_zero и разреши try_or_zero вызвать функцию:

def try_or_zero(func):
    try:
        return func()
    except Exception as e:
        return 0

Теперь вы возразите, что 1/ это не будет работать, если функция ожидает аргументы, а 2/ необходимость написать функцию только для этого - PITA - и оба возражения верны. Надеемся, что в Python также есть ярлык для создания простых анонимных функций, состоящих из одного (даже если сколь угодно сложного) выражения: lambda, Кроме того, функции python (включая "лямбда-функции", которые, технически, являются простыми функциями) закрывают - они захватывают контекст, в котором они определены - так что все это легко обернуть вместе:

a = 42
b = "c"

def add(x, y):
    return x + y

result = try_or_zero(lambda: add(a, b))

Дополнительное примечание об обработке исключений:

Во-первых, не используйте голые, кроме, по крайней мере, поймать Exception (иначе вы можете предотвратить какое-то исключение - например, SysExit- работать как положено).

Также желательно ловить только те исключения, которые вы ожидаете в данный момент. В вашем случае вы можете передать кортеж исключений, которые вы хотите игнорировать, а именно:

def try_or_zero(func, *exceptions):
    if not exceptions:
        exceptions = (Exception,)  
    try:
        return func()
    except exceptions as e:
        return 0


a = 42
b = "c"

def add(x, y):
    return x + y

result = try_or_zero(lambda: add(a, b), TypeError))

что предотвратит ваш код от маскировки непредвиденных ошибок.

И наконец: вы также можете добавить поддержку для возвращаемого значения, отличного от нуля, в случае исключения (не все выражения должны возвращать int):

# XXX : python3 only, python2 doesn't accept
# keyword args after *args

def try_or(func, *exceptions, default=0):
    if not exceptions:
        exceptions = (Exception,)  
    try:
        return func()
    except exceptions as e:
        return 0

# adding lists is legit too,
# so here you may want an empty list as the return value
# instead
a = [1, 2, 3]
# but only to lists
b = ""

result = try_or(lambda: a + b, TypeError, default=[]))

Не нужно беспокоиться с exec и прочее, используйте тот факт, что функции Python являются объектами и, следовательно, могут быть переданы в качестве аргументов

def try_or_zero(exp):
    try:
       return exp()
    except:
       return 0

И просто позвони try_or_zero(my_awesome_func) (без () для вашего метода)

Таким образом, вы можете передать exp как строка в функцию.

def try_or_zero(exp):
    try:
        return eval(exp)
    except:
        return 0

Вы можете достичь этого, заключив свои выражения в функцию. Например:

def ErrorTest():
    # the expression you want to try
    raise Exception

Также ваша функция try должна выглядеть так:

 def try_catch(exp):
    try :
        exp()  # note the paranthesis
    except:
        return 0

И поместите это внутри функции

try_or_zero(ErrorTest)

OutPut: 0

Вы также можете сделать это с помощью функции eval(), но вам придется поместить свой код в строку.

try_or_zero(exp):
    try:
        eval(exp)  # exp must be a string, for example 'raise ValueError'
    except:
        return 0

Передайте аргумент функции в str и выполните exec внутри функции

def try_or_zero(exp):
    try:
        exec(exp)
        return exp
    except:
        return 0

поэтому ваш вызов функции будет таким, как показано ниже: try_or_zero('1==2')

Другие вопросы по тегам