Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #21801 > unrolled thread

How to get a reference of the 'owner' class to which a method belongs in Python 3.X?

Started byCosmia Luna <cosmius@gmail.com>
First post2012-03-16 22:30 -0700
Last post2012-03-17 10:01 +0000
Articles 13 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Cosmia Luna <cosmius@gmail.com> - 2012-03-16 22:30 -0700
    Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Chris Rebert <clp2@rebertia.com> - 2012-03-16 22:51 -0700
    Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Richard Thomas <chardster@gmail.com> - 2012-03-17 00:34 -0700
      Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Cosmia Luna <cosmius@gmail.com> - 2012-03-17 01:11 -0700
    Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Peter Otten <__peter__@web.de> - 2012-03-17 10:25 +0100
      Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Cosmia Luna <cosmius@gmail.com> - 2012-03-17 03:04 -0700
        Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Cosmia Luna <cosmius@gmail.com> - 2012-03-17 05:21 -0700
          Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Cosmia Luna <cosmius@gmail.com> - 2012-03-18 02:42 -0700
          Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Cosmia Luna <cosmius@gmail.com> - 2012-03-18 02:42 -0700
            Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Ian Kelly <ian.g.kelly@gmail.com> - 2012-03-18 10:14 -0600
        Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Cosmia Luna <cosmius@gmail.com> - 2012-03-17 05:21 -0700
      Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Cosmia Luna <cosmius@gmail.com> - 2012-03-17 03:04 -0700
    Re: How to get a reference of the 'owner' class to which a method belongs in Python 3.X? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-03-17 10:01 +0000

#21801 — How to get a reference of the 'owner' class to which a method belongs in Python 3.X?

FromCosmia Luna <cosmius@gmail.com>
Date2012-03-16 22:30 -0700
SubjectHow to get a reference of the 'owner' class to which a method belongs in Python 3.X?
Message-ID<20411334.2044.1331962234309.JavaMail.geo-discussion-forums@yncd8>
I'm porting my existing work to Python 3.X, but...

class Foo:
    def bar(self):
        pass

mthd = Foo.bar

assert mthd.im_class is Foo # this does not work in py3k

So, how can I get a reference to Foo? This is important when writing
decorators, the only way I can think out is:

class Foo:
    def bar(self):
        'Foo' # manually declare the owner class
        pass

mthd = Foo.bar

assert mthd.__globals__[mthd.__doc__] is Foo # this works

class Child(Foo):
    def bar(self):
        'Child' # I have to override all method defined by bar but do nothing
        pass

child_mthd = Child.bar

assert child_mthd.__globals__[child_mthd.__doc__] is Child # this works

But the code above is quite ugly and abuses the __doc__. Is there any
equivalent in py3k of im_class?

Thanks,
Cosmia

[toc] | [next] | [standalone]


#21802

FromChris Rebert <clp2@rebertia.com>
Date2012-03-16 22:51 -0700
Message-ID<mailman.752.1331963468.3037.python-list@python.org>
In reply to#21801
On Fri, Mar 16, 2012 at 10:30 PM, Cosmia Luna <cosmius@gmail.com> wrote:
> I'm porting my existing work to Python 3.X, but...
>
> class Foo:
>    def bar(self):
>        pass
>
> mthd = Foo.bar
>
> assert mthd.im_class is Foo # this does not work in py3k
>
> So, how can I get a reference to Foo? This is important when writing
> decorators,

Could you give an example of such a decorator?

Cheers,
Chris

[toc] | [prev] | [next] | [standalone]


#21805

FromRichard Thomas <chardster@gmail.com>
Date2012-03-17 00:34 -0700
Message-ID<32504391.2142.1331969697343.JavaMail.geo-discussion-forums@ynil17>
In reply to#21801
On Saturday, 17 March 2012 05:30:34 UTC, Cosmia Luna  wrote:
> I'm porting my existing work to Python 3.X, but...
> 
> class Foo:
>     def bar(self):
>         pass
> 
> mthd = Foo.bar
> 
> assert mthd.im_class is Foo # this does not work in py3k

mthd.im_class is the class of mthd.im_self not the class that defined the method.

> 
> So, how can I get a reference to Foo? This is important when writing
> decorators, the only way I can think out is:

Not sure what sort of decorators you're writing. Examples?

You can achieve this with metaclasses but if you're using classes from someone else's code this doesn't necessarily work. Something in inspect module can probably do the trick, check the docs. Frankly though it sounds messy no matter what. It might be better to find an alternative to knowing the class.

> class Foo:
>     def bar(self):
>         'Foo' # manually declare the owner class
>         pass
> 
> mthd = Foo.bar
> 
> assert mthd.__globals__[mthd.__doc__] is Foo # this works
> 
> class Child(Foo):
>     def bar(self):
>         'Child' # I have to override all method defined by bar but do nothing
>         pass
> 
> child_mthd = Child.bar
> 
> assert child_mthd.__globals__[child_mthd.__doc__] is Child # this works
> 
> But the code above is quite ugly and abuses the __doc__. Is there any
> equivalent in py3k of im_class?
> 
> Thanks,
> Cosmia

[toc] | [prev] | [next] | [standalone]


#21806

FromCosmia Luna <cosmius@gmail.com>
Date2012-03-17 01:11 -0700
Message-ID<2929404.2007.1331971877783.JavaMail.geo-discussion-forums@ynbo9>
In reply to#21805
On Saturday, March 17, 2012 3:34:57 PM UTC+8, Richard Thomas wrote:
> On Saturday, 17 March 2012 05:30:34 UTC, Cosmia Luna  wrote:
> > I'm porting my existing work to Python 3.X, but...
> > 
> > class Foo:
> >     def bar(self):
> >         pass
> > 
> > mthd = Foo.bar
> > 
> > assert mthd.im_class is Foo # this does not work in py3k
> 
> mthd.im_class is the class of mthd.im_self not the class that defined the method.
> 
> > 
> > So, how can I get a reference to Foo? This is important when writing
> > decorators, the only way I can think out is:
> 
> Not sure what sort of decorators you're writing. Examples?

A decorator is not necessary but a similar function accept a method. I don't
like any of existing web frameworks and try to write one via werkzeug from
pocoo.

from myapp.controllers import RootController
from werkzeug.routing import Map, Rule
from werkzeug.exceptions import HTTPException
from werkzeug.wrappers import Request

url_map = Map([
    Rule('/', endpoint=RootController.index),
    Rule('/about', endpoint=RootController.about),
    Rule('/contact', endpoint=RootController.contact),
    Rule('/<action>/', endpoint=RootController.otheraction)
])

def application(environ, start_response): #this is a WSGI 1.0 app
    bound_url_map = url_map.bind_to_environ(environ)
    try:
        endpoint, args = bound_url_map.match()
    except HTTPException, e:
        return e(environ, start_response)
    Controller = endpoint.im_class
    controller = Controller(Request(environ))
    if hasattr(controller, '__before__'):
        controller.__before__()
    endpoint(controller)
    if hasattr(controller, '__after__'):
        controller.__after__()
    response = controller.__get_response__():
    return response(environ, start_response)

This is a Pylons-style application, but I don't like others in Pylons.

> 
> You can achieve this with metaclasses but if you're using classes from someone else's code this doesn't necessarily work. Something in inspect module can probably do the trick, check the docs. Frankly though it sounds messy no matter what. It might be better to find an alternative to knowing the class.
> 
> > class Foo:
> >     def bar(self):
> >         'Foo' # manually declare the owner class
> >         pass
> > 
> > mthd = Foo.bar
> > 
> > assert mthd.__globals__[mthd.__doc__] is Foo # this works
> > 
> > class Child(Foo):
> >     def bar(self):
> >         'Child' # I have to override all method defined by bar but do nothing
> >         pass
> > 
> > child_mthd = Child.bar
> > 
> > assert child_mthd.__globals__[child_mthd.__doc__] is Child # this works
> > 
> > But the code above is quite ugly and abuses the __doc__. Is there any
> > equivalent in py3k of im_class?
> > 
> > Thanks,
> > Cosmia

[toc] | [prev] | [next] | [standalone]


#21807

FromPeter Otten <__peter__@web.de>
Date2012-03-17 10:25 +0100
Message-ID<mailman.754.1331976324.3037.python-list@python.org>
In reply to#21801
Cosmia Luna wrote:

> I'm porting my existing work to Python 3.X, but...
> 
> class Foo:
>     def bar(self):
>         pass
> 
> mthd = Foo.bar
> 
> assert mthd.im_class is Foo # this does not work in py3k
> 
> So, how can I get a reference to Foo? This is important when writing
> decorators, the only way I can think out is:
> 
> class Foo:
>     def bar(self):
>         'Foo' # manually declare the owner class
>         pass
> 
> mthd = Foo.bar
> 
> assert mthd.__globals__[mthd.__doc__] is Foo # this works
> 
> class Child(Foo):
>     def bar(self):
>         'Child' # I have to override all method defined by bar but do
>         nothing pass
> 
> child_mthd = Child.bar
> 
> assert child_mthd.__globals__[child_mthd.__doc__] is Child # this works
> 
> But the code above is quite ugly and abuses the __doc__. Is there any
> equivalent in py3k of im_class?

class set_class:
    def __init__(self, method):
        self.method = method
    def __get__(self, instance, class_):
        if instance is None:
            method = self.method
            def f(*args, **kw):
                return method(*args, **kw)
            f.im_class = class_
            f.__name__ = method.__name__
            return f
        return self.method.__get__(instance, class_)
    
class Foo:
    def __init__(self, name):
        self.name = name
    @set_class
    def bar(self):
        print("%s says hello from bar()" % self)
    def __str__(self):
        return self.name

class Bar(Foo):
    pass

assert Foo.bar.im_class is Foo
assert Bar.bar.im_class is Bar

Foo("Fred").bar()
Foo.bar(Foo("Fred"))

Bar("Fred").bar()
Bar.bar(Bar("Fred"))

The cleaner approach is probably:

Rule('/<action>/', endpoint=(RootController, RootController.otheraction))
...
Controller, method = endpoint
controller = Controller(Request(environ))
...
method(controller)

[toc] | [prev] | [next] | [standalone]


#21809

FromCosmia Luna <cosmius@gmail.com>
Date2012-03-17 03:04 -0700
Message-ID<mailman.755.1331978701.3037.python-list@python.org>
In reply to#21807
On Saturday, March 17, 2012 5:25:06 PM UTC+8, Peter Otten wrote:
> Cosmia Luna wrote:
> 
> > I'm porting my existing work to Python 3.X, but...
> > 
> > class Foo:
> >     def bar(self):
> >         pass
> > 
> > mthd = Foo.bar
> > 
> > assert mthd.im_class is Foo # this does not work in py3k
> > 
> > So, how can I get a reference to Foo? This is important when writing
> > decorators, the only way I can think out is:
> > 
> > class Foo:
> >     def bar(self):
> >         'Foo' # manually declare the owner class
> >         pass
> > 
> > mthd = Foo.bar
> > 
> > assert mthd.__globals__[mthd.__doc__] is Foo # this works
> > 
> > class Child(Foo):
> >     def bar(self):
> >         'Child' # I have to override all method defined by bar but do
> >         nothing pass
> > 
> > child_mthd = Child.bar
> > 
> > assert child_mthd.__globals__[child_mthd.__doc__] is Child # this works
> > 
> > But the code above is quite ugly and abuses the __doc__. Is there any
> > equivalent in py3k of im_class?
> 
> class set_class:
>     def __init__(self, method):
>         self.method = method
>     def __get__(self, instance, class_):
>         if instance is None:
>             method = self.method
>             def f(*args, **kw):
>                 return method(*args, **kw)
>             f.im_class = class_
>             f.__name__ = method.__name__
>             return f
>         return self.method.__get__(instance, class_)
>     
> class Foo:
>     def __init__(self, name):
>         self.name = name
>     @set_class
>     def bar(self):
>         print("%s says hello from bar()" % self)
>     def __str__(self):
>         return self.name
> 
> class Bar(Foo):
>     pass
> 
> assert Foo.bar.im_class is Foo
> assert Bar.bar.im_class is Bar
> 
> Foo("Fred").bar()
> Foo.bar(Foo("Fred"))
> 
> Bar("Fred").bar()
> Bar.bar(Bar("Fred"))
> 
> The cleaner approach is probably:
> 
> Rule('/<action>/', endpoint=(RootController, RootController.otheraction))
> ...
> Controller, method = endpoint
> controller = Controller(Request(environ))
> ...
> method(controller)


That's exactly what I want, and I think you're right, the approach below is cleaner.
Rule('/<action>/', endpoint=(RootController, RootController.otheraction)).

Thanks a lot.
Cosmia

[toc] | [prev] | [next] | [standalone]


#21812

FromCosmia Luna <cosmius@gmail.com>
Date2012-03-17 05:21 -0700
Message-ID<mailman.756.1331986866.3037.python-list@python.org>
In reply to#21809
On Saturday, March 17, 2012 6:04:58 PM UTC+8, Cosmia Luna wrote:
> On Saturday, March 17, 2012 5:25:06 PM UTC+8, Peter Otten wrote:
> > Cosmia Luna wrote:
> > 
> > > I'm porting my existing work to Python 3.X, but...
> > > 
> > > class Foo:
> > >     def bar(self):
> > >         pass
> > > 
> > > mthd = Foo.bar
> > > 
> > > assert mthd.im_class is Foo # this does not work in py3k
> > > 
> > > So, how can I get a reference to Foo? This is important when writing
> > > decorators, the only way I can think out is:
> > > 
> > > class Foo:
> > >     def bar(self):
> > >         'Foo' # manually declare the owner class
> > >         pass
> > > 
> > > mthd = Foo.bar
> > > 
> > > assert mthd.__globals__[mthd.__doc__] is Foo # this works
> > > 
> > > class Child(Foo):
> > >     def bar(self):
> > >         'Child' # I have to override all method defined by bar but do
> > >         nothing pass
> > > 
> > > child_mthd = Child.bar
> > > 
> > > assert child_mthd.__globals__[child_mthd.__doc__] is Child # this works
> > > 
> > > But the code above is quite ugly and abuses the __doc__. Is there any
> > > equivalent in py3k of im_class?
> > 
> > class set_class:
> >     def __init__(self, method):
> >         self.method = method
> >     def __get__(self, instance, class_):
> >         if instance is None:
> >             method = self.method
> >             def f(*args, **kw):
> >                 return method(*args, **kw)
> >             f.im_class = class_
> >             f.__name__ = method.__name__
> >             return f
> >         return self.method.__get__(instance, class_)
> >     
> > class Foo:
> >     def __init__(self, name):
> >         self.name = name
> >     @set_class
> >     def bar(self):
> >         print("%s says hello from bar()" % self)
> >     def __str__(self):
> >         return self.name
> > 
> > class Bar(Foo):
> >     pass
> > 
> > assert Foo.bar.im_class is Foo
> > assert Bar.bar.im_class is Bar
> > 
> > Foo("Fred").bar()
> > Foo.bar(Foo("Fred"))
> > 
> > Bar("Fred").bar()
> > Bar.bar(Bar("Fred"))
> > 
> > The cleaner approach is probably:
> > 
> > Rule('/<action>/', endpoint=(RootController, RootController.otheraction))
> > ...
> > Controller, method = endpoint
> > controller = Controller(Request(environ))
> > ...
> > method(controller)
> 
> 
> That's exactly what I want, and I think you're right, the approach below is cleaner.
> Rule('/<action>/', endpoint=(RootController, RootController.otheraction)).
> 
> Thanks a lot.
> Cosmia

Oh I'm wrong.
If I use a decorator, the decorator will NEVER get the owner class even in Python 2.X. The function is just plain function instead of unbound method before the code of a class is fully evaluated. So the decorator ALWAYS receives a plain function.

I'll look into the module inspect and try to get the frame of calling...

Cosmia

[toc] | [prev] | [next] | [standalone]


#21852

FromCosmia Luna <cosmius@gmail.com>
Date2012-03-18 02:42 -0700
Message-ID<mailman.777.1332063743.3037.python-list@python.org>
In reply to#21812
I think I got the way to handle it but with small problem and probably at
unnecessary performance cost. If you're going to use it, be sure rewrite the
code and remove the lines which you don't need. Annnnd, test them, the code
below is only tested on py3.2, and may contains a lot of bugs even in py3.2.
You don't need it in py2.X, really.

----------------------------------BEGIN PYTHON----------------------------------
from functools import wraps
from types import FunctionType

CLASS_REF = 'im_class'

class Py2Type(type):
    def __init__(cls, name, bases, dict_):
        for k, v in dict_.items(): #ref3
            if isinstance(v, FunctionType):
                setattr(v, CLASS_REF, cls)
        for base in bases:
            for k, v in base.__dict__.items():
                if isinstance(v, FunctionType) and k not in dict_:
                    @wraps(v)
                    def wrapper(*args, **kwargs):
                        return v(*args, **kwargs)
                    setattr(wrapper, CLASS_REF, cls)
                    dict_[k] = wrapper
                    setattr(cls, k, wrapper) #ref1
        type.__init__(cls, name, bases, dict_) #ref2

Py2TypeBase = Py2Type('Py2TypeBase', (object, ), {})
-----------------------------------END PYTHON-----------------------------------

And any class inherit(directly or indirectly) from Py2TypeBase can have them
unbound method has a 'im_class' attribute reference to the owner class.

Usage:

Just subclass Py2TypeBase and write anything you want.

----------------------------------BEGIN PYTHON----------------------------------
class Foo(Py2TypeBase):
    def get(self): pass
    def set(self): pass

class Bar(Foo):
    def get(self): pass

assert Foo.get.im_class is Foo
assert Foo.set.im_class is Foo
assert Bar.get.im_class is Bar
assert Bar.set.im_class is Bar

# the code above works, but only the explicitly defined will has the
# im_class attribute, so

assert Foo.__init__.im_class is Foo # this doesn't work.

-----------------------------------END PYTHON-----------------------------------

But it seems that the last line(#ref2) in the Py2Type.__init__ does not work at
all. It seems really weird, 'type' is an instance of 'type' itself, I'm not sure
if I'm calling the unbound method __init__ or bound method __init__.

And the original code does not have the line(#ref1), but because line(#ref2)
does not work, I added them.

It seems type.__new__ calls type.__init__ before it calls Py2Type.__init__,
because dict_ is already copied to cls.__dict__ at line(#ref3).

But 'type' is written in C or some other, it's beyond my ability to read the
code. Can anyone tell me what python does when a class block is fully evaluated
kindly?

Regards,
Cosmia

[toc] | [prev] | [next] | [standalone]


#21853

FromCosmia Luna <cosmius@gmail.com>
Date2012-03-18 02:42 -0700
Message-ID<14929632.47.1332063740635.JavaMail.geo-discussion-forums@ynbq18>
In reply to#21812
I think I got the way to handle it but with small problem and probably at
unnecessary performance cost. If you're going to use it, be sure rewrite the
code and remove the lines which you don't need. Annnnd, test them, the code
below is only tested on py3.2, and may contains a lot of bugs even in py3.2.
You don't need it in py2.X, really.

----------------------------------BEGIN PYTHON----------------------------------
from functools import wraps
from types import FunctionType

CLASS_REF = 'im_class'

class Py2Type(type):
    def __init__(cls, name, bases, dict_):
        for k, v in dict_.items(): #ref3
            if isinstance(v, FunctionType):
                setattr(v, CLASS_REF, cls)
        for base in bases:
            for k, v in base.__dict__.items():
                if isinstance(v, FunctionType) and k not in dict_:
                    @wraps(v)
                    def wrapper(*args, **kwargs):
                        return v(*args, **kwargs)
                    setattr(wrapper, CLASS_REF, cls)
                    dict_[k] = wrapper
                    setattr(cls, k, wrapper) #ref1
        type.__init__(cls, name, bases, dict_) #ref2

Py2TypeBase = Py2Type('Py2TypeBase', (object, ), {})
-----------------------------------END PYTHON-----------------------------------

And any class inherit(directly or indirectly) from Py2TypeBase can have them
unbound method has a 'im_class' attribute reference to the owner class.

Usage:

Just subclass Py2TypeBase and write anything you want.

----------------------------------BEGIN PYTHON----------------------------------
class Foo(Py2TypeBase):
    def get(self): pass
    def set(self): pass

class Bar(Foo):
    def get(self): pass

assert Foo.get.im_class is Foo
assert Foo.set.im_class is Foo
assert Bar.get.im_class is Bar
assert Bar.set.im_class is Bar

# the code above works, but only the explicitly defined will has the
# im_class attribute, so

assert Foo.__init__.im_class is Foo # this doesn't work.

-----------------------------------END PYTHON-----------------------------------

But it seems that the last line(#ref2) in the Py2Type.__init__ does not work at
all. It seems really weird, 'type' is an instance of 'type' itself, I'm not sure
if I'm calling the unbound method __init__ or bound method __init__.

And the original code does not have the line(#ref1), but because line(#ref2)
does not work, I added them.

It seems type.__new__ calls type.__init__ before it calls Py2Type.__init__,
because dict_ is already copied to cls.__dict__ at line(#ref3).

But 'type' is written in C or some other, it's beyond my ability to read the
code. Can anyone tell me what python does when a class block is fully evaluated
kindly?

Regards,
Cosmia

[toc] | [prev] | [next] | [standalone]


#21860

FromIan Kelly <ian.g.kelly@gmail.com>
Date2012-03-18 10:14 -0600
Message-ID<mailman.784.1332087285.3037.python-list@python.org>
In reply to#21853
On Sun, Mar 18, 2012 at 3:42 AM, Cosmia Luna <cosmius@gmail.com> wrote:
> But it seems that the last line(#ref2) in the Py2Type.__init__ does not work at
> all.

I'm not sure what you're expecting it to do, but type.__init__ does
not actually do anything

> It seems really weird, 'type' is an instance of 'type' itself, I'm not sure
> if I'm calling the unbound method __init__ or bound method __init__.

type.__init__ is never bound.

> It seems type.__new__ calls type.__init__ before it calls Py2Type.__init__,
> because dict_ is already copied to cls.__dict__ at line(#ref3).

No, type.__new__ does not call type.__init__ at all.  Rather, it is
type.__new__ that is responsible for copying the dict, not
type.__init__.  For this reason you should override type.__new__ in
your metaclass, not type.__init__.

Cheers,
Ian

[toc] | [prev] | [next] | [standalone]


#21813

FromCosmia Luna <cosmius@gmail.com>
Date2012-03-17 05:21 -0700
Message-ID<23527589.2560.1331986862750.JavaMail.geo-discussion-forums@ynmb12>
In reply to#21809
On Saturday, March 17, 2012 6:04:58 PM UTC+8, Cosmia Luna wrote:
> On Saturday, March 17, 2012 5:25:06 PM UTC+8, Peter Otten wrote:
> > Cosmia Luna wrote:
> > 
> > > I'm porting my existing work to Python 3.X, but...
> > > 
> > > class Foo:
> > >     def bar(self):
> > >         pass
> > > 
> > > mthd = Foo.bar
> > > 
> > > assert mthd.im_class is Foo # this does not work in py3k
> > > 
> > > So, how can I get a reference to Foo? This is important when writing
> > > decorators, the only way I can think out is:
> > > 
> > > class Foo:
> > >     def bar(self):
> > >         'Foo' # manually declare the owner class
> > >         pass
> > > 
> > > mthd = Foo.bar
> > > 
> > > assert mthd.__globals__[mthd.__doc__] is Foo # this works
> > > 
> > > class Child(Foo):
> > >     def bar(self):
> > >         'Child' # I have to override all method defined by bar but do
> > >         nothing pass
> > > 
> > > child_mthd = Child.bar
> > > 
> > > assert child_mthd.__globals__[child_mthd.__doc__] is Child # this works
> > > 
> > > But the code above is quite ugly and abuses the __doc__. Is there any
> > > equivalent in py3k of im_class?
> > 
> > class set_class:
> >     def __init__(self, method):
> >         self.method = method
> >     def __get__(self, instance, class_):
> >         if instance is None:
> >             method = self.method
> >             def f(*args, **kw):
> >                 return method(*args, **kw)
> >             f.im_class = class_
> >             f.__name__ = method.__name__
> >             return f
> >         return self.method.__get__(instance, class_)
> >     
> > class Foo:
> >     def __init__(self, name):
> >         self.name = name
> >     @set_class
> >     def bar(self):
> >         print("%s says hello from bar()" % self)
> >     def __str__(self):
> >         return self.name
> > 
> > class Bar(Foo):
> >     pass
> > 
> > assert Foo.bar.im_class is Foo
> > assert Bar.bar.im_class is Bar
> > 
> > Foo("Fred").bar()
> > Foo.bar(Foo("Fred"))
> > 
> > Bar("Fred").bar()
> > Bar.bar(Bar("Fred"))
> > 
> > The cleaner approach is probably:
> > 
> > Rule('/<action>/', endpoint=(RootController, RootController.otheraction))
> > ...
> > Controller, method = endpoint
> > controller = Controller(Request(environ))
> > ...
> > method(controller)
> 
> 
> That's exactly what I want, and I think you're right, the approach below is cleaner.
> Rule('/<action>/', endpoint=(RootController, RootController.otheraction)).
> 
> Thanks a lot.
> Cosmia

Oh I'm wrong.
If I use a decorator, the decorator will NEVER get the owner class even in Python 2.X. The function is just plain function instead of unbound method before the code of a class is fully evaluated. So the decorator ALWAYS receives a plain function.

I'll look into the module inspect and try to get the frame of calling...

Cosmia

[toc] | [prev] | [next] | [standalone]


#21811

FromCosmia Luna <cosmius@gmail.com>
Date2012-03-17 03:04 -0700
Message-ID<31776112.2291.1331978698664.JavaMail.geo-discussion-forums@ynne2>
In reply to#21807
On Saturday, March 17, 2012 5:25:06 PM UTC+8, Peter Otten wrote:
> Cosmia Luna wrote:
> 
> > I'm porting my existing work to Python 3.X, but...
> > 
> > class Foo:
> >     def bar(self):
> >         pass
> > 
> > mthd = Foo.bar
> > 
> > assert mthd.im_class is Foo # this does not work in py3k
> > 
> > So, how can I get a reference to Foo? This is important when writing
> > decorators, the only way I can think out is:
> > 
> > class Foo:
> >     def bar(self):
> >         'Foo' # manually declare the owner class
> >         pass
> > 
> > mthd = Foo.bar
> > 
> > assert mthd.__globals__[mthd.__doc__] is Foo # this works
> > 
> > class Child(Foo):
> >     def bar(self):
> >         'Child' # I have to override all method defined by bar but do
> >         nothing pass
> > 
> > child_mthd = Child.bar
> > 
> > assert child_mthd.__globals__[child_mthd.__doc__] is Child # this works
> > 
> > But the code above is quite ugly and abuses the __doc__. Is there any
> > equivalent in py3k of im_class?
> 
> class set_class:
>     def __init__(self, method):
>         self.method = method
>     def __get__(self, instance, class_):
>         if instance is None:
>             method = self.method
>             def f(*args, **kw):
>                 return method(*args, **kw)
>             f.im_class = class_
>             f.__name__ = method.__name__
>             return f
>         return self.method.__get__(instance, class_)
>     
> class Foo:
>     def __init__(self, name):
>         self.name = name
>     @set_class
>     def bar(self):
>         print("%s says hello from bar()" % self)
>     def __str__(self):
>         return self.name
> 
> class Bar(Foo):
>     pass
> 
> assert Foo.bar.im_class is Foo
> assert Bar.bar.im_class is Bar
> 
> Foo("Fred").bar()
> Foo.bar(Foo("Fred"))
> 
> Bar("Fred").bar()
> Bar.bar(Bar("Fred"))
> 
> The cleaner approach is probably:
> 
> Rule('/<action>/', endpoint=(RootController, RootController.otheraction))
> ...
> Controller, method = endpoint
> controller = Controller(Request(environ))
> ...
> method(controller)


That's exactly what I want, and I think you're right, the approach below is cleaner.
Rule('/<action>/', endpoint=(RootController, RootController.otheraction)).

Thanks a lot.
Cosmia

[toc] | [prev] | [next] | [standalone]


#21808

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-03-17 10:01 +0000
Message-ID<4f646101$0$29981$c3e8da3$5496439d@news.astraweb.com>
In reply to#21801
On Fri, 16 Mar 2012 22:30:34 -0700, Cosmia Luna wrote:

> I'm porting my existing work to Python 3.X, but...
> 
> class Foo:
>     def bar(self):
>         pass
> 
> mthd = Foo.bar
> 
> assert mthd.im_class is Foo # this does not work in py3k
> 
> So, how can I get a reference to Foo? This is important when writing
> decorators, the only way I can think out is:

I don't believe you can get a reference to Foo just by inspecting the 
function object Foo.bar. (In Python 2.x, Foo.bar would be an unbound 
method, but they no longer exist in Python 3.x.)


> class Foo:
>     def bar(self):
>         'Foo' # manually declare the owner class 
>         pass

A better approach might be to inject a reference to the class after the 
event, using a class decorator:

function = type(lambda: None)

def inject_class(cls):
    for name, obj in vars(cls).items():
        if type(obj) is function:
            obj.owner_class = cls
    return cls


And in use:

py> @inject_class
... class Test:
...     a = 1
...     b = 2
...     def method(self, x):
...         return (x, self)
...
py> Test.a
1
py> Test.method
<function method at 0xb7b21bec>
py> Test.method.owner_class is Test
True


Does this help?



-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web