pyplot font python python-decorators

font - title in figure python



Python-Decoradores (5)

Estoy tratando de aprender Decorators . Entendí el concepto de eso y ahora trato de implementarlo.

Aquí está el código que he escrito. El código se explica por sí mismo. Simplemente verifica si el argumento pasado en int o no.

def wrapper(func): def inner(): if issubclass(x,int): pass else: return ''invalid values'' return inner() @wrapper def add(x,y): return x+y print add(''a'',2)

Está lanzando un error al decir que global name ''x'' is not defined . Entiendo que no está definido en el inner , pero ¿no sabía cómo rectificar este código? ¿A dónde me voy mal?


Esto podría funcionar.

def wrapper(func): def inner(*args,**kwargs): if ((args[0] is int) and (args[1] is int)): pass else: return ''invalid values'' return inner @wrapper def add(x,y): return x+y print add(''a'',2)


¿Qué pasa con esto?

def wrapper(func): def inner(): if isinstance(func,int): return func(x, y) else: return ''invalid values'' return inner()


Hay tres problemas que veo con su código actual.

Primero, estás llamando a la función inner , en lugar de devolverle una referencia.

Segundo, tu función inner no toma los mismos argumentos que la función que estás decorando. En este caso, debe tomar al menos el argumento x explícitamente (algunas funciones internas pueden usar *args y **kwargs exclusivamente, pero aparentemente no son suyos).

Por último, nunca estás llamando a la función envuelta. Si bien esto no es estrictamente necesario (podría ser útil intercambiar un método con un decorador durante el desarrollo), por lo general, debe llamar a la función en algún momento durante el código de la función interna.

Entonces, para resumir todo, creo que quieres que tu código sea algo como esto:

def wrapper(func): def inner(x, y): if issubclass(x, int): # issue 2 return func(x, y) # issue 3 else: return "invalid values" # consider raising an exception here instead! return inner # issue 1


También puede generar una excepción si desea terminar el método de agregar correctamente si falla la verificación de tipo. Me gusta esto

def check_int_types(func): def type_checker(x, y): if issubclass(type(x), int) and issubclass(type(y), int): return func(x, y) raise Exception("Invalid types: {}, {}".format(x, y)) return type_checker @check_int_types def add(a, b): return a + b def main(): x = y = 15.0 print add(x, y) if __name__ == ''__main__'': main()

Resultado:

Traceback (most recent call last): File "deco_test.py", line 17, in <module> main() File "deco_test.py", line 14, in main print add(x, y) File "deco_test.py", line 5, in type_checker raise Exception("Invalid types: {}, {}".format(x, y)) Exception: Invalid types: 15.0, 15.0


Tu decorador debe verse como:

def wrapper(func): def inner(x, y): # inner function needs parameters if issubclass(type(x), int): # maybe you looked for isinstance? return func(x, y) # call the wrapped function else: return ''invalid values'' return inner # return the inner function (don''t call it)

Algunos puntos:

  • issubclass espera una clase como primer argumento (podría reemplazarla con un simple try / except TypeError).
  • la envoltura debe devolver una función, no el resultado de una función llamada
  • En realidad deberías llamar a la función envuelta en la función interna.
  • tu función interna no tenía parámetros

Puedes encontrar una buena explicación de los decoradores here .