Cree varios botones dinámicamente en MFC

Cree varios botones dinámicamente en MFC y suéltelos. ¡Un programa escrito por usted mismo! ¡Muy valioso!

Archivo: n459.com/file/25127180-479632270 Contraseña de acceso: 551685

Los siguientes son irrelevantes:

-------------------------------------------Línea divisoria----- ----------------------------------------

Primero revisemos brevemente la copia en Python.

Copiar tiene funciones correspondientes en muchos lenguajes y Python no es una excepción. Hay dos funciones de copia en Python, una es copia y la otra es copia profunda. Es decir, a menudo se hace referencia a copia profunda y copia superficial. La diferencia entre los dos también es muy simple. En resumen, la copia superficial solo copia el objeto principal, no los objetos secundarios en el objeto principal.

Veamos un ejemplo: en la figura siguiente, b es una copia superficial de a. Podemos ver que después de insertar un 5 en a [2], también hay un 5 adicional en b. Debido a que su subíndice 2 almacena la misma referencia, cuando se inserta a, se produce el mismo cambio en b. También podemos ver que cuando cambiamos a [0], no hay un cambio correspondiente en b. Debido a que un [0] es un número, el número es un valor almacenado directamente en el tipo subyacente en lugar de una referencia.

Corresponde a la copia superficial es la copia profunda. Podemos ver que cuando un elemento se inserta en a [2], la copia profunda de b no cambiará en consecuencia.

Memento
usa copy, podemos implementar la función de memento, su función es hacer una copia de seguridad del objeto. En Python, para un objeto obj, todos sus miembros y funciones y otra información se almacenan en el dict de obj .__ dict__. En otras palabras, si hacemos una copia del __dict__ de un objeto, en realidad es equivalente a una copia del objeto.

Al usar la copia, podemos implementar fácilmente la función memento, primero veamos el código.

desde copia, importación, copia, copia profunda

def memento (obj, deep = False):
state = deepcopy (obj. dict ) if deep else copy (obj. dict )

def restore():
    obj.__dict__.clear()
    obj.__dict__.update(state)

return restore

Memento es una función de orden superior y el resultado que devuelve es la función de ejecución, no el resultado de ejecución específico. Si no está familiarizado con las funciones de orden superior, puede revisar el contenido relacionado de las funciones de orden superior en Python.

La lógica no es difícil de entender, los parámetros que se pasan son un objeto obj y una bandera de tipo bool. Marcar significa usar copia profunda o copia superficial, y obj es el objeto que necesitamos para tomar una instantánea o archivo correspondiente. Esperamos restaurar el contenido sobre la base del marco del objeto sin cambios, por lo que el alcance de nuestra copia es muy claro, es decir, obj. Dict , que almacena toda la información clave del objeto.

Echemos un vistazo a la función de restauración, el contenido es realmente muy simple, con solo dos líneas. La primera línea es borrar el contenido en el __dict__ actual de obj, y el segundo paso es restaurarlo con el estado guardado previamente. De hecho, restore realiza una función de retrotraer obj. Repasemos todo el proceso. Ejecutamos la función memento para obtener la función de restauración.Cuando ejecutamos esta función, el contenido de obj volverá al estado en el que se ejecutó la última vez.

Después de comprender la lógica en el recuerdo, no estamos lejos de darnos cuenta de nuestros asuntos. Tenemos dos métodos de implementación para transacciones, uno es a través de objetos, el otro es a través de decoradores, hablemos de ellos uno por uno.

Objeto de transacción La
implementación orientada a objetos es relativamente simple y es similar a nuestro proceso de transacción habitual. Se deben proporcionar dos funciones en el objeto Transaction, una es de confirmación y la otra es de reversión. Es decir, cuando ejecutamos con éxito, ejecutamos commit y tomamos una instantánea de los resultados de la ejecución. Si la ejecución falla, la reversión revertirá el resultado del objeto al estado de la última confirmación.

Una vez que entendamos la función memento, encontraremos que la confirmación y la reversión corresponden a la ejecución de la función memento y la ejecución de la función de restauración. Por lo que no es difícil para nosotros escribir el código:

clase Transacción:

deep = False
states = []

def __init__(self, deep, *targets):
    self.deep = deep
    self.targets = targets
    self.commit()

def commit(self):
    self.states = [memento(target, self.deep) for target in self.targets]

def rollback(self):
    for a_state in self.states:
        a_state()

Dado que es posible que necesitemos más de un objeto de transacción, los objetivos aquí están diseñados en forma de matriz.

Decorador de transacciones
También podemos implementar la transacción como decorador para que podamos usarla a través de anotaciones.

El principio del código aquí también es el mismo, excepto que la lógica de implementación se basa en decoradores. Si está familiarizado con los decoradores, no es difícil de entender. El argumento [0] aquí es en realidad una instancia de una determinada clase, que es el tema de la transacción que debemos garantizar.

de functools import wraps

def transaccional (func):
@wraps (func)
def wrapper (* args, ** kwargs):
# args [0] is obj
state = memento (args [0])
try:
func (* args, ** kwargs)
excepto Excepción como e:
state ()
raise e
return wrapper
Esta es la forma de escribir un decorador convencional. Por supuesto, también podemos usar clases para implementar decoradores. De hecho, el principio es similar, pero hay algunos detalles que son diferentes.

clase Transaccional:

def __init__(self, method):
    self.method = method

def __get__(self, obj, cls):
    def transaction(*args, **kwargs):
        state = memento(obj)
        try:
            return self.method(*args, **kwargs)
        except Exception as e:
            state()
            raise e
    return transaction

Cuando agregamos esta anotación a un determinado método de clase, cuando ejecutamos obj.xxx, se ejecutará el método __get__ en la clase Transaccional en lugar de obtener la clase Transaccional. Y pase obj y el tipo correspondiente a obj como parámetros, que es el significado de obj y cls aquí. Esta es la práctica convencional de usar clases para implementar decoradores. Publiquemos el código convencional para aprender más.

class Wrapper:
def init (self, func):
wraps (func) (self)

def __call__(self, *args, **kwargs):
    return self.__wrapped__(*args, **kwargs)

def __get__(self, instance, cls):
    if instance is None:
        return self
    else:
        return types.MethodType(self, instance)

Este es un caso en el que se utiliza una clase para implementar un decorador. Podemos ver que la función __get__ devuelve self, lo que significa que devuelve la clase Wrapper. Por lo general, una clase no es directamente ejecutable. Para que sea ejecutable, se implementa una función __call__ para ella. No importa si todavía no lo entiende, puede ignorar esta parte. Tampoco es común implementar decoradores con clases, y podemos estar familiarizados con funciones de orden superior.

Combate real
Finalmente, veamos un ejemplo de aplicación práctica. Hemos implementado una clase NumObj que es compatible con el uso de las dos transacciones anteriores. Puede comparar y ver la diferencia.

class NumObj:
def init (self, value):
self.value = valor

def __repr__(self):
    return '<%s, %r>' % (self.__class__.__name__, self.value)

def increment(self):
    self.value += 1

@transactional
def do_stuff(self):
    self.value += '111'
    self.increment()

if nombre == ' principal ':
num_obj = NumObj (-1)

a_transaction = Transaction(True, num_obj)

Usar transacción

try:
    for i in range(3):
        num_obj.increment()
        print(num_obj)

    a_transaction.commit()
    print('----committed')
    for i in range(3):
        num_obj.increment()
        print(num_obj)
    num_obj.value += 'x'
    print(num_obj)
except Exception:
    a_transaction.rollback()
    print('----rollback')

print(num_obj)

Usar transaccional

print('-- now doing stuff')
num_obj.increment()

try:
    num_obj.do_stuff()
except Exception:
    print('-> doing stuff failed')
    import sys
    import traceback
    traceback.print_exc(file=sys.stdout)

print(num_obj)

A partir del código, no es difícil encontrar que para Transaction, que es una implementación orientada a objetos, necesitamos crear una instancia de Transaction adicional para controlar si realizar una reversión en la captura de prueba. La forma de usar las anotaciones es más flexible, realizará una reversión automáticamente cuando la ejecución falle y no requiera demasiadas operaciones adicionales.

En general, preferimos la forma de usar las anotaciones, porque de esta manera es más concisa y limpia, más pitónica y puede reflejar el poder de Python. El primer método parece bastante satisfactorio, pero la ventaja es que es más legible y la implementación del código es menos difícil. Si necesita utilizarlo en su trabajo real, puede elegir según su situación actual Ambos son buenos métodos.

Supongo que te gusta

Origin blog.csdn.net/gumenghua_com1/article/details/112824293
Recomendado
Clasificación