Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Keyword arguments - strange behaviour?

Reply
Thread Tools

Keyword arguments - strange behaviour?

 
 
Fuzzyman
Guest
Posts: n/a
 
      12-23-2004

Steven Bethard wrote:
> Fuzzyman wrote:
> >>>Steven Bethard wrote:
> >>>>
> >>>>So, one of my really common use cases that takes advantage of the
> >>>>fact that default parameters are evaluated at function definition
> >>>>time:
> >>>>
> >>>>def foo(bar, baz, matcher=re.compile(r'...')):
> >>>> ...
> >>>> text = matcher.sub(r'...', text)
> >>>> ...

> > Sure.. but you also gave an example of an alternative that was

complex,
>
> Interesting. I would have thought that my example was pretty simple.


> Maybe it would be helpful to generalize it to:
>
> def foo(bar, baz, spam=badger(x, y, z)):
> ...
>
> All it does is use a default value that was produced by a function

call.
> I'm surprised you haven't run into this situation before...
>
> Of course, what is complex or simple is a matter of personal opinion.

I
> use this pattern so often that it's quite simple to me, but I guess I


> can understand that if you don't use such a pattern, it might seem
> foreign to you.
>
> Steve



Hello Steve,

It wasn't that part of the example that I thought was over complex.
(although it's not a 'pattern' I use often). You suggested that if we
had dynamic evaluation of default values, you would have to replace it
with :
>>>> class foo(object):
>>>> matcher=re.compile(r'...')
>>>> def __new__(self, bar, baz, matcher=None):
>>>> if matcher is None:
>>>> matcher = self.matcher
>>>> ...
>>>> text = matcher.sub(r'...', text)
>>>> ...


Now that I thought was over complex... when all you wanted to do was
put a constant into your default value !

Having said that I see Steve's point about not knowing the namespace
when the function will be called.
Regards,

Fuzzy
http://www.voidspace.org.uk/python/index.shtml

 
Reply With Quote
 
 
 
 
Alex Martelli
Guest
Posts: n/a
 
      12-24-2004
<(E-Mail Removed)> wrote:
...
> I'm really looking for a neat way to do the following:
>
> def method(a,b,opt1=None,opt2=None,opt3="",opt4=None):
> if opt1 is None: opt1=[]
> if opt2 is None: opt2={}
> if opt4 is None: opt4=[]
>
> Python syntax is normally so neat but this just looks a mess if there
> are lots of parameters.


There's a decorator for that in the Cookbook (sorry, don't recall the
recipe number, but, it's on the site, and it got into the 2nd edition
which we're still expecting to have on paper at PyCon) -- basically
wrapping a function with a wrapper that does a copy.deepcopy on the
defaults values at each call (efficiency of course goes down the drain,
but you _did_ say "apart from efficiency"!-).


Alex
 
Reply With Quote
 
 
 
 
Alex Martelli
Guest
Posts: n/a
 
      12-24-2004
<(E-Mail Removed)> wrote:
...
> the default params are evaluated at the definition. However, I still
> can't give a nice looking solution on how to re-write a function to
> have empty mutable values as default arguments: eg.
>
> def method(a,b,opt1=[],opt2=None,opt3="",opt4={})
>
> How could I re-write this (especially if there are perhaps 20 optional
> parameters,any number of which may have mutable defaults) without
> writing 20 "if opt1 is None: opt1=[]" statements?


I don't have the recipe I mentioned at hand, but what about:

def makebrianhappy(f):
saved_defaults = f.func_defaults
def with_fresh_defaults(*a, **k):
f.func_defaults = copy.deepcopy(saved_defaults)
return f(*a, **k)
with_fresh_defaults.__name__ = f.__name__
return with_fresh_defaults

@ makebrianhappy
def method(a, b, opt1=[], opt2=None, opt3="", opt4={}):
...

I've added spaces after commas to make ME happy too (lack of such spaces
is my least favourite Python irritation, but I guess the semantics of
this (UNTESTED) code would work even without that.


Alex
 
Reply With Quote
 
Steven Bethard
Guest
Posts: n/a
 
      12-25-2004
Fuzzyman wrote:
> It wasn't that part of the example that I thought was over complex.
> (although it's not a 'pattern' I use often). You suggested that if we
> had dynamic evaluation of default values, you would have to replace it
> with :
>
>>>>>class foo(object):
>>>>> matcher=re.compile(r'...')
>>>>> def __new__(self, bar, baz, matcher=None):
>>>>> if matcher is None:
>>>>> matcher = self.matcher
>>>>> ...
>>>>> text = matcher.sub(r'...', text)
>>>>> ...

>
>
> Now that I thought was over complex... when all you wanted to do was
> put a constant into your default value !


Ahh. Yeah, the thing above is a bit complex, but it keeps the same
namespaces -- matcher is only available to foo, not the enclosing
class/module. Point taken of course.

Steve
 
Reply With Quote
 
Fuzzyman
Guest
Posts: n/a
 
      12-28-2004

Steven Bethard wrote:
> Fuzzyman wrote:
> > It wasn't that part of the example that I thought was over complex.
> > (although it's not a 'pattern' I use often). You suggested that if

we
> > had dynamic evaluation of default values, you would have to replace

it
> > with :
> >
> >>>>>class foo(object):
> >>>>> matcher=re.compile(r'...')
> >>>>> def __new__(self, bar, baz, matcher=None):
> >>>>> if matcher is None:
> >>>>> matcher = self.matcher
> >>>>> ...
> >>>>> text = matcher.sub(r'...', text)
> >>>>> ...

> >
> >
> > Now that I thought was over complex... when all you wanted to do

was
> > put a constant into your default value !

>
> Ahh. Yeah, the thing above is a bit complex, but it keeps the same
> namespaces -- matcher is only available to foo, not the enclosing
> class/module. Point taken of course.
>
> Steve


I see. I may be wrong on this... *but* I thought the only time when a
variable defined in the same scope as a function wouldn't be available
in the same namespace is when the function is a global but the variable
isn't ? In which case you deserve a NameError if you try and use the
variable as a default value.......

Are there any other circumstances when they wouldn't be in the same
namespace ?
Regards,

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml

 
Reply With Quote
 
Steven Bethard
Guest
Posts: n/a
 
      12-28-2004
Fuzzyman wrote:
> I see. I may be wrong on this... *but* I thought the only time when a
> variable defined in the same scope as a function wouldn't be available
> in the same namespace is when the function is a global but the variable
> isn't ?


Sorta depends on what you mean by "available in the same namespace":

py> class C(object):
.... def f(matcher=re.compile(r'...')):
.... pass
....
py> class D(object):
.... matcher = re.compile(r'...')
.... def f():
.... pass
....
py> class E(object):
.... class f(object):
.... matcher = re.compile(r'...')
.... def __new__(cls):
.... pass
....
py> c = C()
py> c.matcher
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
AttributeError: 'C' object has no attribute 'matcher'
py> d = D()
py> d.matcher
<_sre.SRE_Pattern object at 0x01142F20>
py> e = E()
py> e.matcher
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
AttributeError: 'E' object has no attribute 'matcher'

Now in all three classes, the callable 'f' can access matcher -- it's
either in f's namespace or within an enclosing namespace.

However, moving the 'matcher' declaration up one level (as in class D)
adds matcher to the enclosing class's namespace. The current code
(class C) and my proposed code (class E) do not add 'matcher' to the
enclosing class's namespace -- they keep it within f's namespace.

This is what I considered to be 'polluting the namespace' -- adding
extra things that aren't used by other parts of the class to the class's
namespace. (Of course, this only holds if, as in my code, matcher is
only needed within f.)

Does that make my problem clearer?

Steve
 
Reply With Quote
 
brian.bird@securetrading.com
Guest
Posts: n/a
 
      01-05-2005
Thanks. In case anyone else is looking, the recipe is at:
http://aspn.activestate.com/ASPN/Coo.../Recipe/303440

(which also shows how to make it work with python2.3 and below since
they don't support decorators)

Brian

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
RE: keyword checker - keyword.kwlist Hamilton, William Python 4 05-13-2007 06:31 AM
keyword checker - keyword.kwlist tom@finland.com Python 6 05-10-2007 04:53 PM
strange behaviour with keyword arguments and inheritance matthewperpick Python 8 04-17-2007 03:06 PM
Keyword arguments in a block, possible with zero arguments? Peter Motzfeldt Ruby 1 03-13-2007 01:33 PM
Difference between default arguments and keyword arguments Edward Diener Python 14 04-05-2004 11:26 PM



Advertisments