2010-05-26 16 views
7

Estoy creando un entorno tipo concha. Mi método original de manejar la entrada del usuario era usar un comando de mapeo del diccionario (cadenas) para métodos de varias clases, haciendo uso del hecho de que las funciones son objetos de primera clase en python.¿Es una mala práctica usar getattr de python extensivamente?

Por razones de flexibilidad (sobre todo para los comandos de análisis), estoy pensando en cambiar mi configuración de modo que estoy usando getattr (comando), para tomar el método que necesito y luego pasarle argumentos al final de mi analizador Otra ventaja de este enfoque es no tener que actualizar mi diccionario de comandos (actualmente implementado estáticamente) cada vez que agrego un nuevo método/comando.

Mi pregunta es doble. En primer lugar, ¿getattr tiene los mismos problemas que eval? En segundo lugar, ¿estaré afectando la eficiencia de mi caparazón? ¿Importa cuántos métodos/comandos tengo? Actualmente estoy viendo 30 comandos, que podrían duplicarse.

+1

si no has mirado pyparsing http://pyparsing.wikispaces.com/ realmente deberías, hay __NO__ razón real para escribir tu propio analizador en python para cualquier cosa. –

+2

Fuzzy, estoy bastante seguro de que puedo pensar en uno, y es para lo que lo estoy haciendo: propósitos de aprendizaje. Antes de comenzar este proyecto actual, no entendía las implicaciones de las funciones como objetos de primera clase. Aunque aprecio la referencia. Lo miraré. – Wilduck

Respuesta

20

La diferencia entre el acceso directo a los atributos y el uso de getattr() debería ser bastante despreciable. Se puede decir la diferencia entre los códigos de bytes las dos versiones mediante el uso del módulo de Python dis para comparar los dos enfoques:

>>> import dis 
>>> dis.dis(lambda x: x.foo) 
    1   0 LOAD_FAST    0 (x) 
       3 LOAD_ATTR    0 (foo) 
       6 RETURN_VALUE   
>>> dis.dis(lambda x: getattr(x, 'foo')) 
    1   0 LOAD_GLOBAL    0 (getattr) 
       3 LOAD_FAST    0 (x) 
       6 LOAD_CONST    0 ('foo') 
       9 CALL_FUNCTION   2 
      12 RETURN_VALUE 

Lo hace, sin embargo, suena como que está desarrollando una cáscara que es muy similar a la forma en la biblioteca de Python cmd hace comandos de conchas de línea. cmd le permite crear conchas que ejecuta los comandos, haciendo coincidir el nombre del comando a una función definida en un objeto cmd.Cmd así:

import cmd 

class EchoCmd(cmd.Cmd): 
    """Simple command processor example.""" 

    def do_echo(self, line): 
     print line 

    def do_EOF(self, line): 
     return True 

if __name__ == '__main__': 
    EchoCmd().cmdloop() 

Usted puede leer más sobre el módulo, ya sea en la documentación, o por lo http://www.doughellmann.com/PyMOTW/cmd/index.html

+1

+1 para la "comprobación de dis". – EOL

+0

Gracias por esta respuesta. Como en mi comentario anterior, realmente estoy escribiendo este shell para fines de aprendizaje. En el futuro, si realmente necesito escribir un intérprete de comandos para algún propósito de producción, usaré cmd. Aunque no sabía nada de dis, gracias por la referencia. – Wilduck

6

¿tiene getattr los mismos problemas que eval?

El código sin código usando eval() es terriblemente molesto de mantener y puede tener serios problemas de seguridad. Llamar al getattr(x, "foo") es solo otra manera de escribir x.foo.

voy a tomar un golpe a la eficacia de mi concha

Será imperceptiblemente más lento si no se encuentra el comando, pero no lo suficiente a la materia. Solo lo notarías si haces benchmarks, con decenas de miles de entradas.

Cuestiones relacionadas