2009-07-17 15 views
11

he escrito algo de código que utiliza atributos de un objeto:Python @property versus performance del método - ¿cuál usar?

class Foo: 
    def __init__(self): 
     self.bar = "baz" 
myFoo = Foo() 
print (myFoo.bar) 

Ahora quieren hacer algún cálculo de fantasía para volver bar. Podría usar @property para hacer que los métodos actúen como el atributo bar, o podría refactorizar mi código para usar myFoo.bar().

¿Debo volver y agregar parecidos a todos mis accesos bar o usar @property? Supongamos que mi código base es pequeño ahora, pero debido a la entropía aumentará.

Respuesta

21

Si es lógicamente una propiedad/atributo del objeto, yo diría que lo mantenga como una propiedad. Si es probable que se parametrice, con lo que quiero decir que puede querer invocar myFoo.bar(someArgs), muerda la viñeta ahora y conviértalo en un método.

En la mayoría de los casos, es poco probable que el rendimiento sea un problema.

7

En casos como estos, me parece mucho mejor elegir la opción que tenga más sentido. No obtendrá ninguna pérdida de rendimiento notable con pequeñas diferencias como estas. Es mucho más importante que su código sea fácil de usar y mantener.

En cuanto a elegir entre usar un método y @property, es una cuestión de gusto, pero como las propiedades se disfrazan como atributos simples, nada complicado debería estar sucediendo. Un método indica que podría ser una operación costosa, y los desarrolladores que usen su código considerarán almacenar en caché el valor en lugar de ir a buscarlo una y otra vez.

Así que de nuevo, no continúe con el rendimiento, siempre tenga en cuenta el mantenimiento frente al rendimiento. Las computadoras se vuelven más y más rápidas a medida que pasa el tiempo. Lo mismo no significa la legibilidad del código.

En resumen, si desea obtener un valor calculado simple, @property es una excelente opción; si desea calcular un valor elaborado, un método lo indica mejor.

1

Para eso está exactamente @property.

3

Me gustaría ir a la refactorización, pero solo por una cuestión de estilo - me parece más claro que los "cálculos sofisticados" podrían estar en curso con una llamada a un método, mientras que yo esperaría que una propiedad fuera casi irrelevante , pero esto es una cuestión de gusto.

No se preocupe por el rendimiento del decorador ... si cree que podría ser un problema, mida el rendimiento en ambos casos y vea cuánto agrega (supongo que será totalmente insignificante si se compara) a tus cálculos de fantasía).

17

Se pregunta sobre el rendimiento es innecesaria cuando es tan fácil de medir:

$ python -mtimeit -s'class X(object): 
> @property 
> def y(self): return 23 
> x=X()' 'x.y' 
1000000 loops, best of 3: 0.685 usec per loop 
$ python -mtimeit -s'class X(object): 

    def y(self): return 23 
x=X()' 'x.y()' 
1000000 loops, best of 3: 0.447 usec per loop 
$ 

(en mi portátil lenta - Si usted se pregunta por qué el segundo caso no tiene indicaciones de concha secundarias, es porque he construido desde el primero con una flecha hacia arriba en bash, y eso repite la estructura de salto de línea, pero no las indicaciones! -).

De modo que, a menos que esté en un caso en el que sepa que más de 200 nanosegundos importará (un bucle interno cerrado que está tratando de optimizar al máximo), puede permitirse usar el enfoque de propiedad; Si realiza algunos cálculos para obtener el valor, los 200+ nanosegundos se convertirán, por supuesto, en una fracción más pequeña del tiempo total empleado.

Estoy de acuerdo con otras respuestas en que si los cálculos son demasiado pesados, o puede que quiera parámetros, etc., es preferible un método; de manera similar, agregaré, si alguna vez necesita esconder el llamamiento en algún lugar pero solo llámalo más tarde, y otros trucos de programación funcional extravagantes; pero quería hacer el punto de rendimiento cuantitativamente, ya que timeit hace tales mediciones tan fáciles! -)

+0

Y los resultados son aún más cercanos (en porcentaje) si no cuenta la creación de instancia 'x', (utilicé la función mágica'% timeit' en iPython): 'x = X();% timeit x.y' -> 1000000 loops, lo mejor de 3: 211 ns por ciclo; 'x = X(); % timeit x.y() '-> 10000000 loops, lo mejor de 3: 169 ns por ciclo –

2

Estoy de acuerdo con lo que la mayoría de la gente aquí ha dicho, hice muchas mediciones al construir modelos hidrológicos en Python hace un par de años y encontré que la velocidad alcanzada al usar @property fue completamente ensombrecida por el cálculo.

A modo de ejemplo, la creación de variables locales del método (eliminando el "factor de puntos" en mis cálculos rendimiento aumentado casi un orden de magnitud más que la eliminación de @property (estos resultados se promedian en una aplicación de escala media).

Buscaría en otro lugar la optimización, cuando sea necesario, y me centraré inicialmente en obtener un código bueno y fácil de mantener escrito. En este punto, si @property es intuitivo en su caso, úselo. Si no, haga un método.

Cuestiones relacionadas