method that can be called from a class and also from an instance

Marc Aymerich glicerinu at gmail.com
Thu Nov 22 17:33:12 CET 2012


On Thursday, November 22, 2012 4:51:30 PM UTC+1, Peter Otten wrote:
> Marc Aymerich wrote:
> 
> 
> 
> > Hi,
> 
> > 
> 
> > I want to create a method within a class that is able to accept either a
> 
> > class or an instance.
> 
> > 
> 
> > class MyClass(object):
> 
> >     @magic_decorator
> 
> >     def method(param):
> 
> >         # param can be MyClass (cls) or an instance of MyClass (self)
> 
> > 
> 
> > so I can do something like:
> 
> > 
> 
> > instance = MyClass()
> 
> > 
> 
> > MyClass.method()
> 
> > instance.method()
> 
> > 
> 
> > I guess the way to go is implementing a custom decorator (@magic_decorator
> 
> > in my example), but, how can I know if the method has been called from the
> 
> > class o from an instance?
> 
> > 
> 
> > Thank you very much!!
> 
> 
> 
> Why would you overload a method that way?

Yep, it's an strange pattern sure it can be done in a better way but this is the best I can think on, the context is:

I'm developing a permission system which can give general permissions for a given class and also specific permissions for a given object.

class Node(object):
   @role
   def has_perm(instance, user)
      if is_class(instance): then global perm for user...
      else: then specific perm for user...


> 
> $ cat class_or_inst.py
> 
> import functools
> 
> 
> 
> class desc(object):
> 
>     def __init__(self, f):
> 
>         self._f = f
> 
>     def __get__(self, inst=None, class_=None):
> 
>         if inst is not None:
> 
>             return functools.partial(self._f, self=inst)
> 
>         elif class_ is not None:
> 
>             return functools.partial(self._f, class_=class_)
> 
>         raise TypeError("nobody expects the Spanish inquisition")
> 
> 
> 
> 
> 
> 
> 
> class A(object):
> 
>     @desc
> 
>     def f(self=None, class_=None):
> 
>         if self is not None:
> 
>             return "instance"
> 
>         elif class_ is not None:
> 
>             return "class"
> 
>         return "unknown"
> 
> $ python -i class_or_inst.py 
> 
> >>> A.f()
> 
> 'class'
> 
> >>> A().f()
> 
> 'instance'
> 
> >>> A.__dict__["f"].__get__()
> 
> Traceback (most recent call last):
> 
>   File "<stdin>", line 1, in <module>
> 
>   File "class_or_inst.py", line 11, in __get__
> 
>     raise TypeError("nobody expects the Spanish inquisition")
> 
> TypeError: nobody expects the Spanish inquisition

you are a genius! I've implemented this on my code and it works as expected ! Thanks :D


More information about the Python-list mailing list