2009-02-12 5 views
2

Предположим, у вас есть небольшая программа калькулятора, которая принимает числа и оператор для выполнения на этих числах в качестве входных данных, а затем распечатывает результат применения указанной операции. Поэтому, если вы введете «4 + 5», он выведет «9». Простой, не так ли? Ну, что я хочу, чтобы иметь возможность написать что-то в этом:Вызов встроенных операторов косвенно в Python

a, op, b = raw_input().split() 
print somehowInvokeOperator(op, a, b) 

Проблема заключается в том, что «somehowInvokeOperator()» часть. Есть ли способ сделать это, не прибегая к (a) eval() или (b) некоторым типам клавиш сопоставления словаря типа «+» и «-» для функций, выполняющих соответствующую операцию? getattr(), похоже, не работает для этого. Мне не нужен этот код для чего-либо, мне просто интересно узнать, можно ли это решить на Python так же элегантно, как на других динамических языках.

+0

Пространства имен в Python в основном реализованы как словари, поэтому даже если 'getattr()' работал, это будет «некоторый тип преобразования словаря». – jfs

+0

Если вы хотите научиться писать компилятор/интерпретатор, посмотрите на это [простое учебное пособие] (http://norvig.com/lispy.html) – erikbwork

ответ

6

В принципе нет, вам, по крайней мере, потребуется словарь или функция для сопоставления символов оператора с их реализациями. На самом деле это немного сложнее, так как не все операторы принимают форму a [op] b, поэтому в целом вам нужно немного разобрать; см. https://docs.python.org/library/operator.html для получения полного списка соответствий и для функций, которые вы, вероятно, захотите использовать для реализации оператора.

Если вы пытаетесь реализовать двоичные арифметические операторы, такие как + - * /% **, то словарь должен быть достаточно хорош.

2

Если вы действительно хотели это сделать, вам понадобится стандартный модуль operator. См. Также Emulating numeric types. И, да, словарь, полный функций, был бы совершенно здоровым динамическим способом сделать это.

import operator 
operations = {'+' : operator.add} 
result = operations[op](a, b) 
+0

Проблема, опять же, в том, что мне нужно будет отобразить " + "на" __add__ ", а также - удивительно достаточно - это не сработает, если a является целым числом, а b является поплавком: >>> (4) .__ добавить __ (4.4) NotImplemented – 2009-02-12 20:07:24

+0

@grg: см. b. __radd __ (a) – joeforker

+0

{'+': lambda a, b: a + b} #so все это inline – hasen

2

Предупреждение: это вообще не питоны !! (Идет против каждого правила в Zen of Python!)

Вот магический словарь, один вкладыш:

ops = eval('{%s}'%','.join([('\''+op + '\' : lambda a,b: a ' + op + ' b') for op in '+-*/%'])) 

Это определяет ваш словарь .. который вы можете использовать

ops['+'](10,4) #returns 14 

в основная идея заключается в сопоставлении каждого оператора с лямбда-функцией:

{ '+' : lambda a,b: a + b } 
+0

Мне это нравится: D. Вы чаще пишете свой код? –

+0

На самом деле, я никогда не использую eval, но в этом случае это были единственные варианты. Это «решение» возникло из моего комментария на ответ joeforker, мне потребовалось некоторое время, чтобы разобраться. – hasen

Смежные вопросы