Попробуйте 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')