Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #21801 > unrolled thread
| Started by | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| First post | 2012-03-16 22:30 -0700 |
| Last post | 2012-03-17 10:01 +0000 |
| Articles | 13 — 6 participants |
Back to article view | Back to comp.lang.python
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
| From | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| Date | 2012-03-16 22:30 -0700 |
| Subject | How 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]
| From | Chris Rebert <clp2@rebertia.com> |
|---|---|
| Date | 2012-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]
| From | Richard Thomas <chardster@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2012-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]
| From | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Cosmia Luna <cosmius@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-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