Python instance methods

This is the essence of what I'm trying to do. I have a list of objects and I know that they have an instance method that looks like this:

def render(self, name, value, attrs)
   # Renders a widget...

I want to (substantially) decorate these functions at runtime as I repeat the list of objects. To make their rendering functions look like this:

def render(self, name, value, attrs)
   self.attrs=attrs
   # Renders a widget...

Two caveats:

  • The rendering function is part of django. I cannot put the decorator in my library (I could, but then I need to support and transfer this change).
  • This is an instance method.

Example: http://wiki.python.org/moin/PythonDecoratorLibrary

Shows how to add a new instance method to a class. The difference here is that I want to switch to the original method after I remember this attrs parameter.

+3
2
def decorate_method(f):
  def wrapper(self, name, value, attrs):
    self.attrs = attrs
    return f(self, name, value, attrs)
  return wrapper

def decorate_class(c):
  for n in dir(c):
    f = getattr(c, n)
    if hasattr(f, 'im_func'):
      setattr(c, n, decorate_method(f.im_func))

, , , , decorate_class(whatever) , , whatever.

+7

"" . , .

class someclass(object):
    def render(self, name, value, attrs):
        print hasattr(self, 'attrs')

class my_render(object):
    def render(self, name, value, attrs):
        self.attrs = attrs # kind of decorating the function here
        return super(my_render, self).render(name, value, attrs)

class my_class(my_render, someclass): 
    pass    

someclass().render(1,2,3) # -> False
my_class().render(1,2,3) # -> True

MI , my_render. mixin; -)

class my_otherclass(my_render, someotherclass): pass
class my_thirdclass(my_render, thirdclass): pass

# or less explicit
classlist = [ someclass, someotherclass ]
newclasses = [ type('my_'+cls.__name__, (my_render,cls), {}) for cls in classlist ]
+3

Source: https://habr.com/ru/post/1721855/


All Articles