J'apprends Python ces derniers jours et j'ai écrit ce morceau de code pour évaluer une expression postfix.
postfix_expression = "34*34*+" stack = [] for char in postfix_expression : try : char = int(char); stack.append(char); except ValueError: if char == '+' : stack.append(stack.pop() + stack.pop()) elif char == '-' : stack.append(stack.pop() - stack.pop()) elif char == '*' : stack.append(stack.pop() * stack.pop()) elif char == '/' : stack.append(stack.pop() / stack.pop()) print stack.pop()
3 Réponses :
le puis votre boucle principale peut ressembler à ceci: p> opérateur code>
module a des fonctions qui implémentent la norme opérateurs arithmétiques. Avec cela, vous pouvez configurer un mappage comme: for char in postfix_expression:
if char in OperatorFunctions:
stack.append(OperatorFunctions[char](stack.pop(), stack.pop()))
else:
stack.append(char)
FYI - opérateur code> Les fonctions semblent être incroyablement lentes.
% TimeIt 1 + 3 Code> - Donne 12.5ns tandis que
% Timeit opérateur.Ajouter (1, 3) code> donne 101n (9 fois plus lent: o)
Il suffit d'utiliser eval ainsi que génération de chaînes:
postfix_expression = "34*34*+" stack = [] for char in postfix_expression: if char in '+-*/': expression = '%d%s%d' % (stack.pop(), char, stack.pop()) stack.append(eval(expression)) else: stack.append(int(char)) print stack.pop()
Venant d'un contexte JS: Eval () en Python est-il aussi mauvais / lent que dans JavaScript?
Je ne sais pas sur la lenteur. Cela peut être dangereux (c'est-à-dire dangereux) s'il n'est pas très soigneusement utilisé, mais ici, il est parfaitement sûr car toute entrée est vérifiée (entiers ou un jeu de caractères limité).
@Boldewyn: Eval est généralement plus lent que des solutions équivalentes qui tirent parti des caractéristiques dynamiques de Python, car il y a une augmentation substantielle dans l'analyse et la compilation de chaque fois que Eval () est appelée. Faire une recherche de dictionnaire et utiliser les fonctions du module d'opérateur (fonctionnalités de commande ["+"] (2, 2)) est d'environ 60 fois plus rapide que d'utiliser Eval (Eval ("2 + 2"))
Cool, merci pour les réponses! Donc, c'est une sorte de la même chose que chez JS ... (concernant la sécurité et la rapidité)
[untested] from operator import add, sub, mul, div # read the docs; this is a tiny part of the operator module despatcher = { '+': add, '-': sub, # etc } opfunc = despatcher[op_char] operand2 = stack.pop() # your - and / are bassackwards stack[-1] = opfunc(stack[-1], operand2)
@ Editeur trop zélé: "Dépatter" est une alternative acceptée (bien que prétendément moins commune) au "répartiteur". J'ai roulé votre édition de retour. S'il vous plaît laissez-le seul.
@John: Est-ce l'un de ces "anglophones" anglophones "vs" American Anglais?
@Ptbnl: Je ne sais pas. FWIW: Google Hit Counts (Millions, 3 SIG. Chiffres): Expédition 8.25, Dispatch 34,6, Dépatter 8.42, Dispatcher 7.98. Inversion intéressante.