Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #16805 > unrolled thread
| Started by | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| First post | 2011-12-07 23:18 -0800 |
| Last post | 2011-12-08 15:56 -0800 |
| Articles | 20 on this page of 32 — 10 participants |
Back to article view | Back to comp.lang.python
I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-07 23:18 -0800
Re: I love the decorator in Python!!! Chris Rebert <clp2@rebertia.com> - 2011-12-08 00:04 -0800
Re: I love the decorator in Python!!! Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-12-08 09:59 +0100
Re: I love the decorator in Python!!! Chris Angelico <rosuav@gmail.com> - 2011-12-08 20:37 +1100
Re: I love the decorator in Python!!! K.-Michael Aye <kmichael.aye@gmail.com> - 2011-12-08 12:22 +0100
Re: I love the decorator in Python!!! Francesco Bochicchio <bieffe62@gmail.com> - 2011-12-09 04:00 -0800
Re: I love the decorator in Python!!! Chris Angelico <rosuav@gmail.com> - 2011-12-08 22:43 +1100
Re: I love the decorator in Python!!! Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-12-09 10:57 +0100
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-09 10:28 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-09 16:21 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-09 16:21 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-10 06:04 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-10 06:09 -0800
Re: I love the decorator in Python!!! alex23 <wuwei23@gmail.com> - 2011-12-11 19:35 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-10 06:09 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-10 06:04 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-09 10:28 -0800
Re: I love the decorator in Python!!! K.-Michael Aye <kmichael.aye@gmail.com> - 2011-12-08 17:24 +0100
Re: I love the decorator in Python!!! Chris Angelico <rosuav@gmail.com> - 2011-12-09 03:38 +1100
Re: I love the decorator in Python!!! alex23 <wuwei23@gmail.com> - 2011-12-08 21:02 -0800
Re: I love the decorator in Python!!! Robert Kern <robert.kern@gmail.com> - 2011-12-09 10:08 +0000
Re: I love the decorator in Python!!! alex23 <wuwei23@gmail.com> - 2011-12-11 19:36 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-11 20:51 -0800
Re: I love the decorator in Python!!! alex23 <wuwei23@gmail.com> - 2011-12-11 21:47 -0800
Re: I love the decorator in Python!!! 88888 Dihedral <dihedral88888@googlemail.com> - 2011-12-12 04:16 -0800
Re: I love the decorator in Python!!! Ethan Furman <ethan@stoneleaf.us> - 2011-12-11 23:47 -0800
Re: I love the decorator in Python!!! Robert Kern <robert.kern@gmail.com> - 2011-12-12 16:27 +0000
Re: I love the decorator in Python!!! alex23 <wuwei23@gmail.com> - 2011-12-12 16:46 -0800
Re: I love the decorator in Python!!! Andrew Berg <bahamutzero8825@gmail.com> - 2011-12-08 10:54 -0600
Re: I love the decorator in Python!!! Andrew Berg <bahamutzero8825@gmail.com> - 2011-12-08 10:55 -0600
Re: I love the decorator in Python!!! Ethan Furman <ethan@stoneleaf.us> - 2011-12-08 15:34 -0800
Re: I love the decorator in Python!!! Ethan Furman <ethan@stoneleaf.us> - 2011-12-08 15:56 -0800
Page 1 of 2 [1] 2 Next page →
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-07 23:18 -0800 |
| Subject | I love the decorator in Python!!! |
| Message-ID | <29996186.628.1323328726122.JavaMail.geo-discussion-forums@prfb7> |
I use the @ decorator to behave exactly like a c macro that does have fewer side effects. I am wondering is there other interesting methods to do the jobs in Python? A lot people complained that no macro in Python. Cheers to the rule of Python : If there's none then just go ahead and build one!
[toc] | [next] | [standalone]
| From | Chris Rebert <clp2@rebertia.com> |
|---|---|
| Date | 2011-12-08 00:04 -0800 |
| Message-ID | <mailman.3398.1323331470.27778.python-list@python.org> |
| In reply to | #16805 |
On Wed, Dec 7, 2011 at 11:18 PM, 88888 Dihedral <dihedral88888@googlemail.com> wrote: > I use the @ decorator to behave exactly like a c macro that > does have fewer side effects. > > I am wondering is there other interesting methods to do the > jobs in Python? * Class decorators (http://www.python.org/dev/peps/pep-3129/ ); i.e. using decorators on a class instead of a function/method * Metaclasses (http://docs.python.org/dev/reference/datamodel.html#customizing-class-creation ); a rather more complicated feature capable of serious black magic * Descriptors (http://docs.python.org/dev/reference/datamodel.html#implementing-descriptors ); probably the most rarely directly used of the three Cheers, Chris -- http://rebertia.com
[toc] | [prev] | [next] | [standalone]
| From | Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> |
|---|---|
| Date | 2011-12-08 09:59 +0100 |
| Message-ID | <jbpu9j$1af$1@r03.glglgl.gl> |
| In reply to | #16805 |
Am 08.12.2011 08:18 schrieb 88888 Dihedral:
> I use the @ decorator to behave exactly like a c macro that
> does have fewer side effects.
>
> I am wondering is there other interesting methods to do the
> jobs in Python?
In combination with a generator, you can do many funny things.
For example, you can build up a string:
def mkstring(f):
"""Turns a string generator into a string,
joining with ", ".
"""
return ", ".join(f())
def create_answer():
@mkstring
def people():
yield "Anna"
yield "John"
yield "Theo"
return "The following people were here: " + people
Many other things are thinkable...
Thomas
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-12-08 20:37 +1100 |
| Message-ID | <mailman.3399.1323337078.27778.python-list@python.org> |
| In reply to | #16812 |
On Thu, Dec 8, 2011 at 7:59 PM, Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> wrote: > Many other things are thinkable... And many more are unthinkable. Can we start an International Obfuscated Python Code Contest? It's the only place such... abhorrences can properly flourish. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | K.-Michael Aye <kmichael.aye@gmail.com> |
|---|---|
| Date | 2011-12-08 12:22 +0100 |
| Message-ID | <mailman.3405.1323343364.27778.python-list@python.org> |
| In reply to | #16812 |
On 2011-12-08 08:59:26 +0000, Thomas Rachel said: > Am 08.12.2011 08:18 schrieb 88888 Dihedral: >> I use the @ decorator to behave exactly like a c macro that >> does have fewer side effects. >> >> I am wondering is there other interesting methods to do the >> jobs in Python? > > In combination with a generator, you can do many funny things. > > > For example, you can build up a string: > > def mkstring(f): > """Turns a string generator into a string, > joining with ", ". > """ > return ", ".join(f()) > > def create_answer(): > @mkstring > def people(): > yield "Anna" > yield "John" > yield "Theo" > > return "The following people were here: " + people > > > Many other things are thinkable... > > > Thomas I am still perplexed about decorators though, am happily using Python for many years without them, but maybe i am missing something? For example in the above case, if I want the names attached to each other with a comma, why wouldn't I just create a function doing exactly this? Why would I first write a single name generator and then decorate it so that I never can get single names anymore (this is the case, isn't it? Once decorated, I can not get the original behaviour of the function anymore. So, above, why not def mkstring(mylist): with the same function declaration and then just call it with a list of names that I generate elsewhere in my program? I just can't identify the use-case for decorators, but as I said, maybe I am missing something. Michael
[toc] | [prev] | [next] | [standalone]
| From | Francesco Bochicchio <bieffe62@gmail.com> |
|---|---|
| Date | 2011-12-09 04:00 -0800 |
| Message-ID | <8e5b46e4-86a9-4192-ac99-7872d08677fc@x7g2000yqb.googlegroups.com> |
| In reply to | #16821 |
On 8 Dic, 12:22, K.-Michael Aye <kmichael....@gmail.com> wrote:
> On 2011-12-08 08:59:26 +0000, Thomas Rachel said:
>
>
>
> > Am 08.12.2011 08:18 schrieb 88888 Dihedral:
> >> I use the @ decorator to behave exactly like a c macro that
> >> does have fewer side effects.
>
> >> I am wondering is there other interesting methods to do the
> >> jobs in Python?
>
> > In combination with a generator, you can do many funny things.
>
> > For example, you can build up a string:
>
> > def mkstring(f):
> > """Turns a string generator into a string,
> > joining with ", ".
> > """
> > return ", ".join(f())
>
> > def create_answer():
> > @mkstring
> > def people():
> > yield "Anna"
> > yield "John"
> > yield "Theo"
>
> > return "The following people were here: " + people
>
> > Many other things are thinkable...
>
> > Thomas
>
> I am still perplexed about decorators though, am happily using Python
> for many years without them, but maybe i am missing something?
> For example in the above case, if I want the names attached to each
> other with a comma, why wouldn't I just create a function doing exactly
> this? Why would I first write a single name generator and then decorate
> it so that I never can get single names anymore (this is the case,
> isn't it? Once decorated, I can not get the original behaviour of the
> function anymore.
> So, above, why not
> def mkstring(mylist):
> with the same function declaration and then just call it with a list of
> names that I generate elsewhere in my program?
> I just can't identify the use-case for decorators, but as I said, maybe
> I am missing something.
>
> Michael
I had/have similar feelings. For instance, this is something that I
tought useful, but then I never used in real code.
The idea was to find a way to automate this code pattern, which I do a
lot:
class SomeClass:
def __init__(self, some, attribute, here ):
self.some, self.attribute, self.here = some, attribute, here
In other words, I often define classes in which the constructor list
of arguments corresponds one-to-one to class attributes.
So I thought of this (it uses class decorators so it only works with
Python 3.x ) :
class FieldsDecorator:
def __init__(self, *names):
self.names = names
def __call__(self, cls):
def constructor(instance, **kwds):
for n,v in kwds.items():
if n in self.names:
setattr(instance, n, v)
else: raise TypeError("%s is not a valid field" % s )
setattr(cls, '__init__', constructor )
return cls
@FieldsDecorator("uno", "due")
class Prova:
pass
p = Prova(uno=12, due=9)
print (p.uno, p.due )
It works and it is nice, but I don't find it compelling enough to use
it. I keep assigning directly the attributes, which is more readable.
Decorators are really useful when you have lot of repetitive
boilercode that you _want_ to hide, since it has little to do with
the problem logic and more to to with the technicalities of the
programming language or of some framework that you are using. It is
called "separating of concerns" I think, and is one of the principles
of Aspect-Oriented Programming (and with decorators you can do some
nice AOP exercises ... ).
Ciao
---
FB
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-12-08 22:43 +1100 |
| Message-ID | <mailman.3408.1323344595.27778.python-list@python.org> |
| In reply to | #16812 |
On Thu, Dec 8, 2011 at 10:22 PM, K.-Michael Aye <kmichael.aye@gmail.com> wrote:
> I am still perplexed about decorators though, am happily using Python for
> many years without them, but maybe i am missing something?
> For example in the above case, if I want the names attached to each other
> with a comma, why wouldn't I just create a function doing exactly this? Why
> would I first write a single name generator and then decorate it so that I
> never can get single names anymore (this is the case, isn't it? Once
> decorated, I can not get the original behaviour of the function anymore.
The example given is a toy. It's hardly useful. However, there are a
number of handy uses for decorators; mostly, they consist of giving a
single simple keyword to a complicated set of logic. One example is
the @classmethod and @staticmethod decorators - the code to implement
them could be uglier than nested inline assembly, but you don't have
to care, because you just type "@staticmethod" in front of your def
statement and it does its magic.
Here's a handy trick that I'm sure someone has done in a more sophisticated way:
def trace(func):
if debugmode:
return lambda *a,**ka:
(print(">"+func.__name__),func(*a,**ka),print("<"+func.__name__))[1]
return func
Then you put @trace in front of all your functions, and if debugmode
is False, nothing will be done - but set it to true, and you get
console output at the entry and exit of each function.
>>> @trace
def test(x):
print("Test! "+x)
return 5
>>> test("asdf")
>test
Test! asdf
<test
5
Again, it's helpful because it condenses all the logic (including the
'debugmode' flag) down to a single high level directive: "Trace this
function".
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> |
|---|---|
| Date | 2011-12-09 10:57 +0100 |
| Message-ID | <jbsm3c$qj1$1@r03.glglgl.gl> |
| In reply to | #16823 |
Am 08.12.2011 12:43 schrieb Chris Angelico:
> On Thu, Dec 8, 2011 at 10:22 PM, K.-Michael Aye<kmichael.aye@gmail.com> wrote:
>> I am still perplexed about decorators though, am happily using Python for
>> many years without them, but maybe i am missing something?
>> For example in the above case, if I want the names attached to each other
>> with a comma, why wouldn't I just create a function doing exactly this? Why
>> would I first write a single name generator and then decorate it so that I
>> never can get single names anymore (this is the case, isn't it? Once
>> decorated, I can not get the original behaviour of the function anymore.
>
> The example given is a toy. It's hardly useful.
Right. It was supposed to be an example.
In my case, I work with a script used to build a XML file. I change this
script from time to time in order to match the requirements.
Here I find it useful just to add some more yield statements for adding
entries.
But now that I think again about it, it's more an example for
generators, not so much for decorators - which I like as well.
*****
But some useful examples for decorators include
1. "Threadifying" a function, i.e. turning it into a Thread object, or
into a callable which in turn starts a thread according to the given
parameters.
2. Automatically calling a function if the given module is executed as a
script, a kind of replacement for the "if __name__ == '__main__':" stuff.
3. Meta decorators:
I find it annoying to have to wrap the function given to the decorator
into another one, modifying its properties and returning that in turn.
def wrapfunction(decorated):
"""Wrap a function taking (f, *a, **k) and replace it with a
function taking (f) and returning a function taking (*a, **k) which
calls our decorated function.
"""
from functools import wraps
@wraps(decorated)
def wrapped_outer(f):
@wraps(f)
def wrapped_inner(*a, **k):
return decorated(f, *a, **k)
return wrapped_inner
return wrapped_outer
makes it much easier to create decorators which just wrap a function
into another, extending its funtionality:
@wrapfunction
def return_list(f, *a, **k)
return list(f(*a, **k))
is much easier and IMHO much better to read than
def return_list(f):
"""Wrap a function taking (f, *a, **k) and replace it with a
function taking (f) and returning a function taking (*a, **k) which
calls our decorated function.
"""
from functools import wraps
@wraps(f)
def wrapped(*a, **k):
return list(f, *a, **k)
return wrapped
- especially if used multiple times.
3a. This is a modified case of my first example: If you want a function
to assemble and return a list instead of a generator object, but prefer
"yield" over "ret=[]; ret.append();...", you can do that with this
@return_list.
4. So-called "indirect decorators":
@spam(eggs)
def foo(bar):
pass
are as well quite tricky to build when taking
def indirdeco(ind):
from functools import update_wrapper, wraps
upd=wraps(ind)
# outer wrapper: replaces a call with *a, **k with an updated
# lambda, getting the function to be wrapped and applying it and
# *a, **k to ind.
outerwrapper=lambda *a, **k: upd(lambda f: ind(f, *a, **k))
# We update this as well:
return upd(outerwrapper)
# We don't update f nor the result of ind() - it is the callee's
# business.
It is kind of reverse to 3.
@indirdeco
def addingdeco(f, offset):
return lambda *a, **k: f(*a, **k) + offset
# Here should maybe be wrapped - it is just supposed to be an
# example.
5. Creating a __all__ for a module. Instead of maintaining it somewhere
centrally, you can take a
class AllList(list):
"""list which can be called in order to be used as a __all__-adding
decorator"""
def __call__(self, obj):
"""for decorators"""
self.append(obj.__name__)
return obj
, do a __all__ = AllList()
and subsequently decorate each function with
@__all__
6. Re-use a generator:
A generator object is creted upon calling the generator function with
parameters and can be used only once. A object wrapping this generator
might be useful.
# Turn a generator into a iterable object calling the generator.
class GeneratorIterable(object):
"""Take a parameterless generator function and call it on every
iteration."""
def __init__(self, gen):
# Set object attribute.
self.gen = gen
def __iter__(self):
# Class attribute calls object attribute in order to keep
# namespace variety small.
return self.gen()
@GeneratorIterable
def mygen():
yield 1
yield 2
list(mygen) -> [1, 2]
list(mygen) -> [1, 2] # again, without the ()
Might be useful if the object is to be transferred to somewhere else.
*****
Some of these decorators are more useful, some less if seen standalone,
but very handy if creating other decorators.
HTH nevertheless,
Thomas
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-09 10:28 -0800 |
| Message-ID | <17457040.1331.1323455329763.JavaMail.geo-discussion-forums@pret21> |
| In reply to | #16823 |
On Thursday, December 8, 2011 7:43:12 PM UTC+8, Chris Angelico wrote:
> On Thu, Dec 8, 2011 at 10:22 PM, K.-Michael Aye <kmicha...@gmail.com> wrote:
> > I am still perplexed about decorators though, am happily using Python for
> > many years without them, but maybe i am missing something?
> > For example in the above case, if I want the names attached to each other
> > with a comma, why wouldn't I just create a function doing exactly this? Why
> > would I first write a single name generator and then decorate it so that I
> > never can get single names anymore (this is the case, isn't it? Once
> > decorated, I can not get the original behaviour of the function anymore.
>
> The example given is a toy. It's hardly useful. However, there are a
> number of handy uses for decorators; mostly, they consist of giving a
> single simple keyword to a complicated set of logic. One example is
> the @classmethod and @staticmethod decorators - the code to implement
> them could be uglier than nested inline assembly, but you don't have
> to care, because you just type "@staticmethod" in front of your def
> statement and it does its magic.
>
> Here's a handy trick that I'm sure someone has done in a more sophisticated way:
>
> def trace(func):
> if debugmode:
> return lambda *a,**ka:
> (print(">"+func.__name__),func(*a,**ka),print("<"+func.__name__))[1]
> return func
>
> Then you put @trace in front of all your functions, and if debugmode
> is False, nothing will be done - but set it to true, and you get
> console output at the entry and exit of each function.
>
> >>> @trace
> def test(x):
> print("Test! "+x)
> return 5
>
> >>> test("asdf")
> >test
> Test! asdf
> <test
> 5
>
> Again, it's helpful because it condenses all the logic (including the
> 'debugmode' flag) down to a single high level directive: "Trace this
> function".
>
> ChrisA
I did use decorators to turn functions into iterables to be traced.
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-09 16:21 -0800 |
| Message-ID | <mailman.3485.1323476480.27778.python-list@python.org> |
| In reply to | #16928 |
On Saturday, December 10, 2011 2:28:49 AM UTC+8, 88888 Dihedral wrote:
> On Thursday, December 8, 2011 7:43:12 PM UTC+8, Chris Angelico wrote:
> > On Thu, Dec 8, 2011 at 10:22 PM, K.-Michael Aye <kmic...@gmail.com> wrote:
> > > I am still perplexed about decorators though, am happily using Python for
> > > many years without them, but maybe i am missing something?
> > > For example in the above case, if I want the names attached to each other
> > > with a comma, why wouldn't I just create a function doing exactly this? Why
> > > would I first write a single name generator and then decorate it so that I
> > > never can get single names anymore (this is the case, isn't it? Once
> > > decorated, I can not get the original behaviour of the function anymore.
> >
> > The example given is a toy. It's hardly useful. However, there are a
> > number of handy uses for decorators; mostly, they consist of giving a
> > single simple keyword to a complicated set of logic. One example is
> > the @classmethod and @staticmethod decorators - the code to implement
> > them could be uglier than nested inline assembly, but you don't have
> > to care, because you just type "@staticmethod" in front of your def
> > statement and it does its magic.
> >
> > Here's a handy trick that I'm sure someone has done in a more sophisticated way:
> >
> > def trace(func):
> > if debugmode:
> > return lambda *a,**ka:
> > (print(">"+func.__name__),func(*a,**ka),print("<"+func.__name__))[1]
> > return func
> >
> > Then you put @trace in front of all your functions, and if debugmode
> > is False, nothing will be done - but set it to true, and you get
> > console output at the entry and exit of each function.
> >
> > >>> @trace
> > def test(x):
> > print("Test! "+x)
> > return 5
> >
> > >>> test("asdf")
> > >test
> > Test! asdf
> > <test
> > 5
> >
> > Again, it's helpful because it condenses all the logic (including the
> > 'debugmode' flag) down to a single high level directive: "Trace this
> > function".
> >
> > ChrisA
>
> I did use decorators to turn functions into iterables to be traced.
It is easy to use decorators in python to mimic those programs in Erlang.
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-09 16:21 -0800 |
| Message-ID | <6527773.1257.1323476471157.JavaMail.geo-discussion-forums@prkz16> |
| In reply to | #16928 |
On Saturday, December 10, 2011 2:28:49 AM UTC+8, 88888 Dihedral wrote:
> On Thursday, December 8, 2011 7:43:12 PM UTC+8, Chris Angelico wrote:
> > On Thu, Dec 8, 2011 at 10:22 PM, K.-Michael Aye <kmic...@gmail.com> wrote:
> > > I am still perplexed about decorators though, am happily using Python for
> > > many years without them, but maybe i am missing something?
> > > For example in the above case, if I want the names attached to each other
> > > with a comma, why wouldn't I just create a function doing exactly this? Why
> > > would I first write a single name generator and then decorate it so that I
> > > never can get single names anymore (this is the case, isn't it? Once
> > > decorated, I can not get the original behaviour of the function anymore.
> >
> > The example given is a toy. It's hardly useful. However, there are a
> > number of handy uses for decorators; mostly, they consist of giving a
> > single simple keyword to a complicated set of logic. One example is
> > the @classmethod and @staticmethod decorators - the code to implement
> > them could be uglier than nested inline assembly, but you don't have
> > to care, because you just type "@staticmethod" in front of your def
> > statement and it does its magic.
> >
> > Here's a handy trick that I'm sure someone has done in a more sophisticated way:
> >
> > def trace(func):
> > if debugmode:
> > return lambda *a,**ka:
> > (print(">"+func.__name__),func(*a,**ka),print("<"+func.__name__))[1]
> > return func
> >
> > Then you put @trace in front of all your functions, and if debugmode
> > is False, nothing will be done - but set it to true, and you get
> > console output at the entry and exit of each function.
> >
> > >>> @trace
> > def test(x):
> > print("Test! "+x)
> > return 5
> >
> > >>> test("asdf")
> > >test
> > Test! asdf
> > <test
> > 5
> >
> > Again, it's helpful because it condenses all the logic (including the
> > 'debugmode' flag) down to a single high level directive: "Trace this
> > function".
> >
> > ChrisA
>
> I did use decorators to turn functions into iterables to be traced.
It is easy to use decorators in python to mimic those programs in Erlang.
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-10 06:04 -0800 |
| Message-ID | <mailman.3494.1323525860.27778.python-list@python.org> |
| In reply to | #16937 |
Just wrap the exec() to spawn for fun.
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-10 06:09 -0800 |
| Message-ID | <mailman.3495.1323526190.27778.python-list@python.org> |
| In reply to | #16952 |
Wrap functions to yield is somewhat like a sub-threading in Erlang.
[toc] | [prev] | [next] | [standalone]
| From | alex23 <wuwei23@gmail.com> |
|---|---|
| Date | 2011-12-11 19:35 -0800 |
| Message-ID | <37dda2ec-0ff7-4df0-96a7-182656cefede@f36g2000prj.googlegroups.com> |
| In reply to | #16954 |
On Dec 11, 12:09 am, 88888 Dihedral <dihedral88...@googlemail.com> wrote: > Wrap functions to yield is somewhat like a sub-threading in Erlang. Okay, now that you've replied to yourself several times, I'm convinced you're really a markov chainer. You might want to get your owner to tweak your response filter.
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-10 06:09 -0800 |
| Message-ID | <28734265.1226.1323526187915.JavaMail.geo-discussion-forums@prie17> |
| In reply to | #16952 |
Wrap functions to yield is somewhat like a sub-threading in Erlang.
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-10 06:04 -0800 |
| Message-ID | <30440550.1225.1323525857598.JavaMail.geo-discussion-forums@prie17> |
| In reply to | #16937 |
Just wrap the exec() to spawn for fun.
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2011-12-09 10:28 -0800 |
| Message-ID | <mailman.3483.1323455868.27778.python-list@python.org> |
| In reply to | #16823 |
On Thursday, December 8, 2011 7:43:12 PM UTC+8, Chris Angelico wrote:
> On Thu, Dec 8, 2011 at 10:22 PM, K.-Michael Aye <kmicha...@gmail.com> wrote:
> > I am still perplexed about decorators though, am happily using Python for
> > many years without them, but maybe i am missing something?
> > For example in the above case, if I want the names attached to each other
> > with a comma, why wouldn't I just create a function doing exactly this? Why
> > would I first write a single name generator and then decorate it so that I
> > never can get single names anymore (this is the case, isn't it? Once
> > decorated, I can not get the original behaviour of the function anymore.
>
> The example given is a toy. It's hardly useful. However, there are a
> number of handy uses for decorators; mostly, they consist of giving a
> single simple keyword to a complicated set of logic. One example is
> the @classmethod and @staticmethod decorators - the code to implement
> them could be uglier than nested inline assembly, but you don't have
> to care, because you just type "@staticmethod" in front of your def
> statement and it does its magic.
>
> Here's a handy trick that I'm sure someone has done in a more sophisticated way:
>
> def trace(func):
> if debugmode:
> return lambda *a,**ka:
> (print(">"+func.__name__),func(*a,**ka),print("<"+func.__name__))[1]
> return func
>
> Then you put @trace in front of all your functions, and if debugmode
> is False, nothing will be done - but set it to true, and you get
> console output at the entry and exit of each function.
>
> >>> @trace
> def test(x):
> print("Test! "+x)
> return 5
>
> >>> test("asdf")
> >test
> Test! asdf
> <test
> 5
>
> Again, it's helpful because it condenses all the logic (including the
> 'debugmode' flag) down to a single high level directive: "Trace this
> function".
>
> ChrisA
I did use decorators to turn functions into iterables to be traced.
[toc] | [prev] | [next] | [standalone]
| From | K.-Michael Aye <kmichael.aye@gmail.com> |
|---|---|
| Date | 2011-12-08 17:24 +0100 |
| Message-ID | <mailman.3428.1323361468.27778.python-list@python.org> |
| In reply to | #16812 |
On 2011-12-08 11:43:12 +0000, Chris Angelico said:
> On Thu, Dec 8, 2011 at 10:22 PM, K.-Michael Aye <kmichael.aye@gmail.com> wrote:
>> I am still perplexed about decorators though, am happily using Python for
>> many years without them, but maybe i am missing something?
>> For example in the above case, if I want the names attached to each other
>> with a comma, why wouldn't I just create a function doing exactly this? Why
>> would I first write a single name generator and then decorate it so that I
>> never can get single names anymore (this is the case, isn't it? Once
>> decorated, I can not get the original behaviour of the function anymore.
>
> The example given is a toy. It's hardly useful. However, there are a
> number of handy uses for decorators; mostly, they consist of giving a
> single simple keyword to a complicated set of logic. One example is
> the @classmethod and @staticmethod decorators - the code to implement
> them could be uglier than nested inline assembly, but you don't have
> to care, because you just type "@staticmethod" in front of your def
> statement and it does its magic.
>
> Here's a handy trick that I'm sure someone has done in a more
> sophisticated way:
>
> def trace(func):
> if debugmode:
> return lambda *a,**ka:
> (print(">"+func.__name__),func(*a,**ka),print("<"+func.__name__))[1]
> return func
>
> Then you put @trace in front of all your functions, and if debugmode
> is False, nothing will be done - but set it to true, and you get
> console output at the entry and exit of each function.
>
>>>> @trace
> def test(x):
> print("Test! "+x)
> return 5
>
>>>> test("asdf")
>> test
> Test! asdf
> <test
> 5
>
> Again, it's helpful because it condenses all the logic (including the
> 'debugmode' flag) down to a single high level directive: "Trace this
> function".
>
> ChrisA
I understand this one, it seems really useful. And maybe i start to
sense some more applicability. Like this, with extra flags that could
be set at run time, I could influence the way a function is executed
without designing the function too complex, but by decorating it, which
at the end could be easier to read than complicated if-then statements
in the function.
Thanks for your example.
Michael
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-12-09 03:38 +1100 |
| Message-ID | <mailman.3430.1323362318.27778.python-list@python.org> |
| In reply to | #16812 |
On Fri, Dec 9, 2011 at 3:24 AM, K.-Michael Aye <kmichael.aye@gmail.com> wrote: > I understand this one, it seems really useful. And maybe i start to sense > some more applicability. Like this, with extra flags that could be set at > run time, I could influence the way a function is executed without designing > the function too complex, but by decorating it, which at the end could be > easier to read than complicated if-then statements in the function. Right, and less duplication usually results in less bugs, too. Obviously if you go to any greater level of complexity than this you'd want to break the lambda out into a proper function, and possibly play with an indent level (increment on call, decrement on return). You can also easily add the run-time check, and anything else you want to do, too. It'll still all be buried away in the definition of trace(), and on functions that you want to trace, you need still only have "@trace" and nothing else. One piece of sophistication that I would rather like to see, but don't know how to do. Instead of *args,**kwargs, is it possible to somehow copy in the function's actual signature? I was testing this out in IDLE, and the fly help for the function no longer gave useful info about its argument list. This is why I say that this has almost certainly been done before in a much better way. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | alex23 <wuwei23@gmail.com> |
|---|---|
| Date | 2011-12-08 21:02 -0800 |
| Message-ID | <0aae460e-caf1-44ce-b228-e6943fc75b7f@24g2000prd.googlegroups.com> |
| In reply to | #16848 |
On Dec 9, 2:38 am, Chris Angelico <ros...@gmail.com> wrote: > One piece of sophistication that I would rather like to see, but don't > know how to do. Instead of *args,**kwargs, is it possible to somehow > copy in the function's actual signature? I was testing this out in > IDLE, and the fly help for the function no longer gave useful info > about its argument list. The 3rd party 'decorator' module takes care of issues like docstrings & function signatures. I'd really like to see some of that functionality in the stdlib though.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web