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


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

When do default parameters get their values set?

Started bybSneddon <w.g.sneddon@gmail.com>
First post2014-12-08 14:10 -0800
Last post2014-12-08 20:37 -0500
Articles 7 — 6 participants

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


Contents

  When do default parameters get their values set? bSneddon <w.g.sneddon@gmail.com> - 2014-12-08 14:10 -0800
    Re: When do default parameters get their values set? Chris Angelico <rosuav@gmail.com> - 2014-12-09 09:28 +1100
    Re: When do default parameters get their values set? Chris Kaynor <ckaynor@zindagigames.com> - 2014-12-08 14:28 -0800
    Re: When do default parameters get their values set? Dave Angel <davea@davea.name> - 2014-12-08 17:30 -0500
    Re: When do default parameters get their values set? Tim Chase <python.list@tim.thechases.com> - 2014-12-08 16:26 -0600
    Re: When do default parameters get their values set? bSneddon <w.g.sneddon@gmail.com> - 2014-12-08 15:35 -0800
    Re: When do default parameters get their values set? Terry Reedy <tjreedy@udel.edu> - 2014-12-08 20:37 -0500

#82149 — When do default parameters get their values set?

FrombSneddon <w.g.sneddon@gmail.com>
Date2014-12-08 14:10 -0800
SubjectWhen do default parameters get their values set?
Message-ID<8c10ecec-c057-4580-9711-94c0a5151646@googlegroups.com>
I ran into an issue setting variables from a GUI module that imports a back end module.  My approach was wrong obviously but what is the best way to set values in a back end module.

#module name beTest.py

cfg = { 'def' : 'blue'}

def printDef(argT = cfg['def']):
	print argT
 

#module name feTest
import beTest

beTest.cfg['def'] = "no red"
beTest.printDef()



This prints blue.      I suppose because I am changing a local copy of cfg dictionary.  What is the write approach here?


Thanks

Bill

[toc] | [next] | [standalone]


#82151

FromChris Angelico <rosuav@gmail.com>
Date2014-12-09 09:28 +1100
Message-ID<mailman.16738.1418077685.18130.python-list@python.org>
In reply to#82149
On Tue, Dec 9, 2014 at 9:10 AM, bSneddon <w.g.sneddon@gmail.com> wrote:
> I ran into an issue setting variables from a GUI module that imports a back end module.  My approach was wrong obviously but what is the best way to set values in a back end module.
>
> #module name beTest.py
>
> cfg = { 'def' : 'blue'}
>
> def printDef(argT = cfg['def']):
>         print argT

They're set when you define the function, and become attributes of the function.

If you want to lazily fetch the defaults, here's one common idiom:

def printDef(argT=None):
    """Print the argT value, defaults to cfg['def']"""
    if argT is None: argT = cfg['def']
    print(argT)

This depends on None not being a meaningful argument value, of course.
If you need to have any object at all able to be passed in, you'd need
to create a dedicated sentinel object, or use *args and unpack
yourself; but for a lot of cases, None works fine.

ChrisA

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


#82152

FromChris Kaynor <ckaynor@zindagigames.com>
Date2014-12-08 14:28 -0800
Message-ID<mailman.16739.1418077725.18130.python-list@python.org>
In reply to#82149

[Multipart message — attachments visible in raw view] — view raw

On Mon, Dec 8, 2014 at 2:10 PM, bSneddon <w.g.sneddon@gmail.com> wrote:

> I ran into an issue setting variables from a GUI module that imports a
> back end module.  My approach was wrong obviously but what is the best way
> to set values in a back end module.
>
> #module name beTest.py
>
> cfg = { 'def' : 'blue'}
>
> def printDef(argT = cfg['def']):

        print argT


Here is your problem. The default argument value is evaulated at the time
the function is defined, not when it is called, so argT will boung to
'blue' by default, unless overridden in the call.
In this simple case, you could just change the function to:

def printDef():
    print cfg['def']

In more complicated cases, where you actually need to pass in the argument
with a default, the best way is to use a sentinel value (I'm using None in
the case):

def printDef(argT = None):
    argT = argT or cfg['def'] # If argT could be False or another "falsy"
value, use "argT = argT if argT is not None else cfg['def']". This is also
useful if None needs to be a valid value.
    print argT


>
>
> #module name feTest
> import beTest
>
> beTest.cfg['def'] = "no red"
> beTest.printDef()
>
>
>
> This prints blue.      I suppose because I am changing a local copy of cfg
> dictionary.  What is the write approach here?

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


#82153

FromDave Angel <davea@davea.name>
Date2014-12-08 17:30 -0500
Message-ID<mailman.16740.1418077879.18130.python-list@python.org>
In reply to#82149
On 12/08/2014 05:10 PM, bSneddon wrote:
> I ran into an issue setting variables from a GUI module that imports a back end module.  My approach was wrong obviously but what is the best way to set values in a back end module.
>

To answer the subject line, the default parameter(s) are evaluated when 
the function is compiled, and then stored with the function.  So in this 
case the default for argT is an immutable string "blue"  Being 
immutable, nothing will change that for the run of the program.

> #module name beTest.py
>
> cfg = { 'def' : 'blue'}
>
> def printDef(argT = cfg['def']):
> 	print argT
>
>
> #module name feTest
> import beTest
>
> beTest.cfg['def'] = "no red"
> beTest.printDef()
>
>
>
> This prints blue.      I suppose because I am changing a local copy of cfg dictionary.  What is the write approach here?
>

You're not making a local copy of any dictionary.  The symptoms you have 
would be identical even if you run beTest.py directly (with those two 
lines added, of course).

The RIGHT approach depends on what your goal is here.  Obviously this is 
simplified from some more complex use, but you haven't stated what your 
desires are, so I don't necessarily know how to achieve them.

There is only one dictionary, and it does change when you you say:
    beTest.cfg['def'] = "no red"

But if you need to do a lookup in that dictionary upon calling 
primtDef(), then you're going to make the evaluation at that time, not 
at default-time.

How about the following, fairly common idiom for default values:

def printDef(argT = None]):
     if argT = None:
         argT = cfg['def']
     print argT





-- 
DaveA

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


#82154

FromTim Chase <python.list@tim.thechases.com>
Date2014-12-08 16:26 -0600
Message-ID<mailman.16741.1418078546.18130.python-list@python.org>
In reply to#82149
On 2014-12-08 14:10, bSneddon wrote:
> I ran into an issue setting variables from a GUI module that
> imports a back end module.  My approach was wrong obviously but
> what is the best way to set values in a back end module.
> 
> #module name beTest.py
> 
> cfg = { 'def' : 'blue'}
> 
> def printDef(argT = cfg['def']):

At this point (after the "def" has completed defining the function),
the expression is evaluated and assigned to the default argument.

> beTest.cfg['def'] = "no red"
> beTest.printDef()
> 
> This prints blue.      I suppose because I am changing a local copy
> of cfg dictionary.  What is the write approach here?

Well, you can bind to a default dictionary rather than an entry in
that dictionary:


  cfg = {'def': 'blue'}
  def printDef(config=cfg):
    ...
    access(config['def'])

which will make the look-up happen at run-time rather than
definition/bind-time.

  beTest.cfg['def'] = 'Red!'
  beTest.printDef()
  # should print "Red!"

-tkc


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


#82156

FrombSneddon <w.g.sneddon@gmail.com>
Date2014-12-08 15:35 -0800
Message-ID<1d8cda49-8949-44a2-997f-5ae3fc6a5013@googlegroups.com>
In reply to#82149
Thanks to all.  I now understand what is happening.   Originally wrote a script  be executed from command line.   No want to use Gui to change defaults.   Will refactor to fix where necessary.

On Monday, December 8, 2014 5:10:58 PM UTC-5, bSneddon wrote:
> I ran into an issue setting variables from a GUI module that imports a back end module.  My approach was wrong obviously but what is the best way to set values in a back end module.
> 
> #module name beTest.py
> 
> cfg = { 'def' : 'blue'}
> 
> def printDef(argT = cfg['def']):
> 	print argT
>  
> 
> #module name feTest
> import beTest
> 
> beTest.cfg['def'] = "no red"
> beTest.printDef()
> 
> 
> 
> This prints blue.      I suppose because I am changing a local copy of cfg dictionary.  What is the write approach here?
> 
> 
> Thanks
> 
> Bill

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


#82167

FromTerry Reedy <tjreedy@udel.edu>
Date2014-12-08 20:37 -0500
Message-ID<mailman.16751.1418089099.18130.python-list@python.org>
In reply to#82149
 >>> def f(a="default "+"arg value"): return a

 >>> f.__defaults__
('default arg value',)

Before any calls, the expression has be evaluated.  When f() is called 
with no arg, the local name 'a' is associated with
'default arg value'. Then code execution begins. Use dir(f), for 
instance, to invesigate internals.

-- 
Terry Jan Reedy

[toc] | [prev] | [standalone]


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


csiph-web