Verifique los posibles efectos secundarios del método sin cambiar nada Pythonicamente

En este momento, tengo los siguientes métodos de clase:

def check_capacity(self, at_index)
def update_capacity(self, at_index)

El primero devuelve un valor booleano, mientras que el segundo cambia una variable de instancia. El problema es que ambos métodos hacen cosas muy similares. Siento que estoy violando DRY?

Me gustaría tener un método:

def update_capacity(self, at_index)

que puedo usar como:

if update_capacity(at_index):

eso crearía los efectos secundarios previstos si los efectos secundarios son deseables, y de lo contrario devolvería False.

Mi intento fue copiar la variable de instancia, verificar si la copia se modificó de manera deseable y luego establecer la variable de instancia en la copia si es correcta y devolver True, o no y devolver False de lo contrario. Sin embargo, ¡esto no funciona con estructuras de datos mutables (como listas)!

¿Debería estar haciendo esto con una "copia profunda"? ¿O hay una mejor manera de hacer esto? Me gustaría ser lo más pitónico posible.

EDITAR

El sistema check_capacity itera a través de la variable de instancia y verifica si hacer el cambio violaría una condición.

El sistema update_capacity itera a través de la variable de instancia y realiza el cambio, sabiendo que no se violará la condición.

Ambos tienen un código muy similar.

preguntado el 03 de mayo de 12 a las 18:05

No estoy del todo seguro de lo que está tratando de hacer, pero ¿una property ¿ayuda? -

"El primero devuelve un valor booleano, mientras que el segundo cambia una variable de instancia". Esto no suena como si me estuvieran haciendo lo mismo. No entiendo por qué quieres fusionar los dos métodos. -

¿Puede proporcionar más información sobre qué hacen esos dos métodos y qué tienen en común? -

¿Alguna vez llamas a un método sin llamar al otro cerca de él? -

2 Respuestas

Tengo el presentimiento de que esas dos funciones juntas logran resolver su problema sin golpearlo exactamente en la cabeza. Si tengo este derecho, tú quieres tener update_capacity o cambias algo o regresas False si no se desea cambiar algo.

Me parece que podrá lograr esta funcionalidad agregando el mecanismo de verificación de check_capacity dentro update_capacity, realizando la verificación de condición antes de ejecutar el cuerpo de update_capacity:

def update_capacity(self, at_index):
    if <condition from check_capacity>:
        <body of update_capacity>
    else:
        return False

Por supuesto, este código devolverá None si la condición es verdadera, por lo que si desea mantener ordenadas las firmas de su función, puede regresar True o algo dependiendo de lo que se ajuste al resto de su código.

contestado el 03 de mayo de 12 a las 19:05

Gracias por tu respuesta. Lamento que mi edición no haya sido más clara: la función update_capacity está modificando cosas en un iterador. La función check_capacity pasa por el iterador y se asegura de que la condición no se viole EN CUALQUIER PARTE del iterador. Por lo tanto, el iterador pasado a update_capacity puede no cumplir la condición, por ejemplo, a la mitad del iterador, pero en ese momento la primera mitad del iterador se modifica, ¡cuando no debería haberlo hecho! ¿Es esto útil? - jakecar

Podría pasar por el iterador dos veces en la misma función. - Grayson

If check_capacity se aplica a más de un lugar, conviértalo en un decorador que se asegure de lanzar una excepción si no se cumple la restricción/verificación.

Me gusta

@check_capacity
def update_capacity(...)
    # Does the job and does not return anything

If check_capacity no se usa en ningún otro lugar, simplemente ponga la lógica dentro update_capacity.

Editar: También esto

si actualización_capacidad (en_índice):

es ambiguo en el mejor de los casos. ¿La función va a ver si puedo actualizar? ¿Realmente va a actualizar/mutar algo?

Es evidente que estas 2 funciones deben estar separadas.

contestado el 03 de mayo de 12 a las 23:05

¿Por qué es mejor usar un decorador que mantener la lógica adentro? update_capacity? - Grayson

Es una técnica común para separar problemas ortogonales. Así que no siempre es una mejor manera. Depende mucho del panorama general de su código, que no tengo. Por cierto, lo que sugirió (acerca de devolver Verdadero/Falso), no es una buena práctica o pitónico. Cuando mutó una estructura, no debe devolver nada (consulte, por ejemplo, las estructuras integradas de Python y sus métodos). if update_capacity(..) es ambiguo y equivocado. Debería haber un método diferente que verifique la capacidad (devolviendo Verdadero/Falso) y otro que modifique la capacidad (devolviendo Ninguno). - planificar

Eso no responde a mi pregunta. el porqué ¿Es una técnica común? ¿Qué lo hace superior? Mi instinto es decir que mejora la legibilidad y puede SECAR el código repetitivo, pero ¿eso es todo? - Grayson

1) No lo hace superior por defecto. Por favor, lea de nuevo el primera línea de mi respuesta al cartel y mi comentario para ti. 2) Tu instinto es básicamente correcto. Además, puede mantener la lógica de distintas funciones/procedimientos sin relación. por ejemplo, el check_capacityLa lógica/código de podría cambiar sin cambiar en absoluto el código interno de update_capacity. Además, puedes encadenar decoradores uno encima del otro. Eso sería útil si tuviéramos muchas "restricciones". Django usa decoradores extensivamente, @login_required y @user_passes_test son buenos ejemplos para comprobar si quieres. - planificar

Gracias rantanplan. Su respuesta es esencialmente lo que estoy haciendo. Sin embargo, siento que estoy violando DRY. Mi check_capacity pasa por un iterador y ve SI la modificación de cada objeto del iterador alguna vez rompería la condición. Si lo hace en algún lugar, no se debe llamar a update_capacity. Sin embargo, check_capacity y update_capacity tienen un código muy similar ya que update_capacity está realizando las modificaciones que check_capacity solo está verificando. Perdón por los nombres ambiguos de las funciones, en su mayoría son irrelevantes. Estoy tratando de abstraerme de la parte de los efectos secundarios de las funciones. - jakecar

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.