Так как вы принимаете пользовательский ввод, самый безопасный способ - точно определить, что является допустимым вводом:
dispatcher={'add':add}
w='add'
try:
function=dispatcher[w]
except KeyError:
raise ValueError('invalid input')
Если вы хотите оценивать строки типа 'add(3,4)'
, вы можете использовать safe eval :
eval('add(3,4)',{'__builtins__':None},dispatcher)
eval
в целом может быть опасно при применении к пользовательскому вводу. Вышеуказанное безопаснее, поскольку __builtins__
отключено, а locals
ограничено dispatcher
. Кто-то умнее, чем я, мог бы по-прежнему вызывать проблемы, но я не мог сказать вам, как это сделать. Strike>
ВНИМАНИЕ: Даже eval(..., {'__builtins__':None}, dispatcher)
- небезопасно для применения к пользовательскому вводу. Злонамеренный пользователь может запустить произвольные функции на вашем компьютере , если ему будет предоставлена возможность оценить его строку в eval
.
Вы ищете условное присвоение:
a ||= b # Assign if a isn't already set
и || operator
a = b || 2 # Assign if b is assigned, or assign 2
x = b || 2
Это ( ??
в C #) называется оператором объединения.
В Ruby закорачивающие логические операторы ( ||
, &&
, и
и или
) не возвращают true
или false
, а возвращают первый операнд, определяющий результат всего выражения. Это работает, потому что у Ruby довольно простое представление об истине. Или, скорее, у него довольно простое представление о лжи: nil
ложно, и очевидно, ложно
ложно. Все остальное истинно.
Итак, поскольку ||
истинно, когда хотя бы один из его операндов истинен, и операнды оцениваются слева направо верно, это означает, что a || b
возвращает a
, когда a
истинно. Но когда a
ложно, тогда результат выражения зависит исключительно от b
, и, таким образом, возвращается b
.
Это означает, что, поскольку nil
ложно, вы можете просто используйте ||
вместо ??
в приведенных вами примерах. (Существует также изящный оператор a || = b
, который работает как a || a = b
, но не совсем так.)
Однако это ] работает только , потому что вы не используете логические значения в своих примерах. Если вы планируете иметь дело с логическими значениями, это не сработает:
b = false
x = b || 2 # x should be == false, but will be 2
В этом случае вам придется использовать #nil?
и условное выражение:
b = false
x = unless b.nil? then b else 2 end # x should be == 2
или использовать тернарное условное выражение оператор:
b = false
x = b.nil? ? 2 : b # x should be == false
Если хотите, можете обернуть это красивым методом:
class Object
def _? b = nil
return self
end
end
class NilClass
def _? b = nil
return yield if block_given?
return b
end
end
b = false
x = b._? { 2 } # x should be == false
x = b._? 2 # x should be == false
Этот милый фрагмент, полученный с помощью полиморфизма,