Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #17038 > unrolled thread
| Started by | Henrik Faber <hfaber@invalid.net> |
|---|---|
| First post | 2011-12-12 14:27 +0100 |
| Last post | 2011-12-12 16:35 +0100 |
| Articles | 7 — 3 participants |
Back to article view | Back to comp.lang.python
Confusion about decorators Henrik Faber <hfaber@invalid.net> - 2011-12-12 14:27 +0100
Re: Confusion about decorators Andrea Crotti <andrea.crotti.0@gmail.com> - 2011-12-12 13:37 +0000
Re: Confusion about decorators Henrik Faber <hfaber@invalid.net> - 2011-12-12 14:45 +0100
Re: Confusion about decorators Arnaud Delobelle <arnodel@gmail.com> - 2011-12-12 13:45 +0000
Re: Confusion about decorators Henrik Faber <hfaber@invalid.net> - 2011-12-12 14:52 +0100
Re: Confusion about decorators Arnaud Delobelle <arnodel@gmail.com> - 2011-12-12 14:01 +0000
Re: Confusion about decorators Henrik Faber <hfaber@invalid.net> - 2011-12-12 16:35 +0100
| From | Henrik Faber <hfaber@invalid.net> |
|---|---|
| Date | 2011-12-12 14:27 +0100 |
| Subject | Confusion about decorators |
| Message-ID | <jc4vg9$8eo$1@speranza.aioe.org> |
Hi group,
I'm a bit confused regarding decorators. Recently started playing with
them with Python3 and wanted (as an excercise) to implement a simple
type checker first: I know there are lots of them out there, this is
actually one of the reasons I chose that particular function (to compare
my solution against other, proven solutions).
Starting with a blank slate, I did something along the lines of:
class _TypeCheckedFunction():
def __init__(self, decoratedfunction):
self._decoratedfunction = decoratedfunction
def __call__(self, *args, **kwargs):
[...] Actual checking
def typecheck(wrappedfunction):
checkfunction = _TypeCheckedFunction(wrappedfunction)
functools.update_wrapper(checkfunction, wrappedfunction)
return checkfunction
And decorate my methods like
@typecheck
def setbar(self, bar: str):
This works somewhat. The problem is, however, when the method is
actually called. This is what happens:
1. The decorator is called upon import of the decorated class. It
creates a _TypeCheckedFunction(setbar) object.
2. When setbar is actually called (blubb.setbar("fooobar")), the
__call__ method of the previously created _TypeCheckedFunction is invoked.
3. When trying to call self._decoratedfunction from within that object,
this fails: "self" is missing! self._decoratedfunction is only the
*function*, not the bound function of the object that contains setbar().
Therefore I cannot proceed here.
Solutions that I have seen working usually consist of two functions
wrapped in each other, but I do not know why the additional introduction
of a class makes everything fail.
Can someone please enlighten me?
Best regards,
Henrik
[toc] | [next] | [standalone]
| From | Andrea Crotti <andrea.crotti.0@gmail.com> |
|---|---|
| Date | 2011-12-12 13:37 +0000 |
| Message-ID | <mailman.3543.1323697057.27778.python-list@python.org> |
| In reply to | #17038 |
On 12/12/2011 01:27 PM, Henrik Faber wrote:
> Hi group,
>
> I'm a bit confused regarding decorators. Recently started playing with
> them with Python3 and wanted (as an excercise) to implement a simple
> type checker first: I know there are lots of them out there, this is
> actually one of the reasons I chose that particular function (to compare
> my solution against other, proven solutions).
>
> Starting with a blank slate, I did something along the lines of:
>
> class _TypeCheckedFunction():
> def __init__(self, decoratedfunction):
> self._decoratedfunction = decoratedfunction
>
> def __call__(self, *args, **kwargs):
> [...] Actual checking
>
> def typecheck(wrappedfunction):
> checkfunction = _TypeCheckedFunction(wrappedfunction)
> functools.update_wrapper(checkfunction, wrappedfunction)
> return checkfunction
>
> And decorate my methods like
>
> @typecheck
> def setbar(self, bar: str):
>
> This works somewhat. The problem is, however, when the method is
> actually called. This is what happens:
>
> 1. The decorator is called upon import of the decorated class. It
> creates a _TypeCheckedFunction(setbar) object.
> 2. When setbar is actually called (blubb.setbar("fooobar")), the
> __call__ method of the previously created _TypeCheckedFunction is invoked.
> 3. When trying to call self._decoratedfunction from within that object,
> this fails: "self" is missing! self._decoratedfunction is only the
> *function*, not the bound function of the object that contains setbar().
> Therefore I cannot proceed here.
>
> Solutions that I have seen working usually consist of two functions
> wrapped in each other, but I do not know why the additional introduction
> of a class makes everything fail.
>
> Can someone please enlighten me?
>
> Best regards,
> Henrik
Not sure how that could work in general, what does "bar: str" should do?
Is that a dictionary?
Anyway there is already an implementation if you're interested for type
checking:
http://oakwinter.com/code/typecheck/
You can have a look at how they do it.
[toc] | [prev] | [next] | [standalone]
| From | Henrik Faber <hfaber@invalid.net> |
|---|---|
| Date | 2011-12-12 14:45 +0100 |
| Message-ID | <jc50h4$b5g$1@speranza.aioe.org> |
| In reply to | #17039 |
On 12.12.2011 14:37, Andrea Crotti wrote: > On 12/12/2011 01:27 PM, Henrik Faber wrote: >> Hi group, >> >> I'm a bit confused regarding decorators. Recently started playing with >> them with Python3 and wanted (as an excercise) to implement a simple >> type checker first: I know there are lots of them out there, this is >> actually one of the reasons I chose that particular function (to compare >> my solution against other, proven solutions). > > Not sure how that could work in general, what does "bar: str" should do? > Is that a dictionary? No. It's PEP 3107 function annotations. > Anyway there is already an implementation if you're interested for type > checking: > http://oakwinter.com/code/typecheck/ *sigh* no, not really -- this is exactly why I wrote "I know there are lots of them out there". I've actually seen and run http://code.activestate.com/recipes/577299-method-signature-type-checking-decorator-for-pytho/ However, this doesn't do it for me -- I want to know why my solution fails, not just use some other solution without really understanding it. I really would like to understand what's going on. I'm especially puzzled about the fact that in my solution, __call__ is called with only the method's arguments (i.e. "fooobar") in my example instead of two arguments (self, "fooobar"). Best regards, Henrik
[toc] | [prev] | [next] | [standalone]
| From | Arnaud Delobelle <arnodel@gmail.com> |
|---|---|
| Date | 2011-12-12 13:45 +0000 |
| Message-ID | <mailman.3544.1323697523.27778.python-list@python.org> |
| In reply to | #17038 |
On 12 December 2011 13:27, Henrik Faber <hfaber@invalid.net> wrote:
> Hi group,
>
> I'm a bit confused regarding decorators. Recently started playing with
> them with Python3 and wanted (as an excercise) to implement a simple
> type checker first: I know there are lots of them out there, this is
> actually one of the reasons I chose that particular function (to compare
> my solution against other, proven solutions).
>
> Starting with a blank slate, I did something along the lines of:
>
> class _TypeCheckedFunction():
> def __init__(self, decoratedfunction):
> self._decoratedfunction = decoratedfunction
>
> def __call__(self, *args, **kwargs):
> [...] Actual checking
>
> def typecheck(wrappedfunction):
> checkfunction = _TypeCheckedFunction(wrappedfunction)
> functools.update_wrapper(checkfunction, wrappedfunction)
> return checkfunction
>
> And decorate my methods like
>
> @typecheck
> def setbar(self, bar: str):
>
> This works somewhat. The problem is, however, when the method is
> actually called. This is what happens:
>
> 1. The decorator is called upon import of the decorated class. It
> creates a _TypeCheckedFunction(setbar) object.
> 2. When setbar is actually called (blubb.setbar("fooobar")), the
> __call__ method of the previously created _TypeCheckedFunction is invoked.
> 3. When trying to call self._decoratedfunction from within that object,
> this fails: "self" is missing! self._decoratedfunction is only the
> *function*, not the bound function of the object that contains setbar().
> Therefore I cannot proceed here.
>
> Solutions that I have seen working usually consist of two functions
> wrapped in each other, but I do not know why the additional introduction
> of a class makes everything fail.
>
> Can someone please enlighten me?
You can (need to?) use the descriptor protocol to deal with methods.
from functools import partial
class _TypeCheckedFunction():
def __init__(self, decoratedfunction):
self._decoratedfunction = decoratedfunction
def __call__(self, *args, **kwargs):
[...] Actual checking
def __get__(self, obj, objtype):
return partial(self, obj)
(Untested)
HTH
--
Arnaud
[toc] | [prev] | [next] | [standalone]
| From | Henrik Faber <hfaber@invalid.net> |
|---|---|
| Date | 2011-12-12 14:52 +0100 |
| Message-ID | <jc50ui$c84$1@speranza.aioe.org> |
| In reply to | #17041 |
On 12.12.2011 14:45, Arnaud Delobelle wrote:
>> Can someone please enlighten me?
>
> You can (need to?) use the descriptor protocol to deal with methods.
>
> from functools import partial
[...]
> def __get__(self, obj, objtype):
> return partial(self, obj)
Whoa. This is absolutely fantastic, it now works as expected (I get a
reference to "self").
I am very amazed -- I've been programming Python for about 5 years now
and have never even come close to something as a "descriptor protocol".
Python never ceases to amaze me. Do you have any beginners guide how
this works? The Pydoc ("Data Model") is comprehensive, but I really
don't know where to start to look.
Still amazed!
Best regards,
Henrik
[toc] | [prev] | [next] | [standalone]
| From | Arnaud Delobelle <arnodel@gmail.com> |
|---|---|
| Date | 2011-12-12 14:01 +0000 |
| Message-ID | <mailman.3545.1323698494.27778.python-list@python.org> |
| In reply to | #17042 |
On 12 December 2011 13:52, Henrik Faber <hfaber@invalid.net> wrote:
> On 12.12.2011 14:45, Arnaud Delobelle wrote:
>
>>> Can someone please enlighten me?
>>
>> You can (need to?) use the descriptor protocol to deal with methods.
>>
>> from functools import partial
> [...]
>> def __get__(self, obj, objtype):
>> return partial(self, obj)
>
> Whoa. This is absolutely fantastic, it now works as expected (I get a
> reference to "self").
>
> I am very amazed -- I've been programming Python for about 5 years now
> and have never even come close to something as a "descriptor protocol".
> Python never ceases to amaze me. Do you have any beginners guide how
> this works? The Pydoc ("Data Model") is comprehensive, but I really
> don't know where to start to look.
Well, I've been using Python for 10 years :) The best reference I know is:
http://users.rcn.com/python/download/Descriptor.htm
--
Arnaud
[toc] | [prev] | [next] | [standalone]
| From | Henrik Faber <hfaber@invalid.net> |
|---|---|
| Date | 2011-12-12 16:35 +0100 |
| Message-ID | <jc56vl$sd2$1@speranza.aioe.org> |
| In reply to | #17043 |
On 12.12.2011 15:01, Arnaud Delobelle wrote:
>> I am very amazed -- I've been programming Python for about 5 years now
>> and have never even come close to something as a "descriptor protocol".
>> Python never ceases to amaze me. Do you have any beginners guide how
>> this works? The Pydoc ("Data Model") is comprehensive, but I really
>> don't know where to start to look.
>
> Well, I've been using Python for 10 years :) The best reference I know is:
>
> http://users.rcn.com/python/download/Descriptor.htm
Everyone starts out as a Padawan and I am no exception :-)
Maybe five years from now I'll also have made my way to be a Python Jedi
and also shake the ins and outs of descriptors out of my sleeve :-)
But I can only repeat myself: Python is such an exceptional language,
the more and more I know about it, the more I fall in love! Fantastic. I
wish we had these types of language when I was a kid!
Best regards and thanks again,
Henrik
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web