2011-08-18 11 views
9

me ocurrió con el siguiente código para decorar los métodos de instancia usando un decorador que requiere la instancia a sí mismo como un argumento:Python: hay alguna irregularidad con dinámicamente la asignación de los métodos de instancia como instancia atribuye

from functools import wraps 

def logging_decorator(tricky_instance): 
    def wrapper(fn): 
     @wraps(fn) 
     def wrapped(*a, **kw): 
      if tricky_instance.log: 
       print("Calling %s.." % fn.__name__) 
      return fn(*a, **kw) 
     return wrapped 
    return wrapper  

class Tricky(object): 
    def __init__(self, log): 
     self.log = log 
     self.say_hi = logging_decorator(self)(self.say_hi) 

    def say_hi(self): 
     print("Hello, world!") 


i1 = Tricky(log=True) 
i2 = Tricky(log=False) 

i1.say_hi() 
i2.say_hi() 

Esto parece un gran trabajo , pero me temo que puede haber pasado por alto algunos efectos secundarios involuntarios de este truco. ¿Estoy a punto de pegarme un tiro en el pie, o es seguro?

Tenga en cuenta que en realidad no quiero utilizar esto para el registro, es el ejemplo más breve y significativo que podría surgir.

+0

Parece legítimo. En mi humilde opinión. – Evpok

Respuesta

2

Creo que estaba tratando de ser innecesariamente inteligente. Parece haber una solución vergonzosamente más simple:

from functools import wraps 

def logging_decorator(fn): 
    @wraps(fn) 
    def wrapped(self, *a, **kw): 
     if self.log: 
      print("Calling %s.." % fn.__name__) 
     return fn(self, *a, **kw) 
    return wrapped 

class Tricky(object): 
    def __init__(self, log): 
     self.log = log 

    @logging_decorator 
    def say_hi(self): 
     print("Hello, world!") 

i1 = Tricky(log=True) 
i2 = Tricky(log=False) 

i1.say_hi() 
i2.say_hi() 
4

No tengo muy claro por qué querrías hacer esto alguna vez. Si desea asignar un nuevo tipo de método de utilizar dinámicamente types:

import types 

class Tricky(object): 
    def __init__(self): 
     def method(self): 
      print('Hello') 
     self.method = types.MethodType(method, self) 

si quieres hacer algo con el ejemplo, lo hace en el método __init__. Si lo que desea el acceso a la instancia del método en el interior del decorador, puede utilizar el atributo im_self:

def decorator(tricky_instance): 
    def wrapper(meth): 
     print(meth.im_self == tricky_instance) 
     return meth 
    return wrapper 

En lo personal, creo que esto está virando en Tal-I-Shouldn't-uso-decoradores tierra.

+0

Deseo recuperar automáticamente los métodos de instancia en problemas de red (temporales), indicados por excepciones. Qué excepciones son temporales y cuáles permanentes depende de la instancia real (las instancias representan objetos de Amazon S3 cuyas garantías de coherencia dependen de la ubicación de almacenamiento). – Nikratio

+0

No entiendo para qué es válido el código. ¿Podrías elaborar? – Nikratio

+1

Mi código crea un nuevo método de instancia en '__init__'. Supongo que estás intentando escribir un decorador, y quieres que el decorador tenga acceso a la instancia del método que se está decorando, para generalizar al decorador. – zeekay

Cuestiones relacionadas