Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #82227 > unrolled thread
| Started by | "bSneddon" <bsneddon@1:249/999.remove-cdt-this> |
|---|---|
| First post | 2014-12-09 11:32 -0500 |
| Last post | 2014-12-09 11:32 -0500 |
| Articles | 17 — 12 participants |
Back to article view | Back to comp.lang.python
When do default parameters get their values set? "bSneddon" <bsneddon@1:249/999.remove-cdt-this> - 2014-12-09 11:32 -0500
Re: When do default parameters get their values set? "Chris Angelico" <chris.angelico@1:249/999.remove-cdt-this> - 2014-12-09 11:32 -0500
Re: When do default parameters get their values set? "Dave Angel" <dave.angel@1:249/999.remove-cdt-this> - 2014-12-09 11:32 -0500
Re: When do default parameters get their values set? Duncan Booth <duncan.booth@invalid.invalid> - 2014-12-09 21:18 +0000
Re: When do default parameters get their values set? random832@fastmail.us - 2014-12-09 18:07 -0500
Re: When do default parameters get their values set? Rustom Mody <rustompmody@gmail.com> - 2014-12-09 18:44 -0800
Re: When do default parameters get their values set? random832@fastmail.us - 2014-12-10 13:38 -0500
Re: When do default parameters get their values set? Rustom Mody <rustompmody@gmail.com> - 2014-12-10 18:18 -0800
Re: When do default parameters get their values set? Chris Angelico <rosuav@gmail.com> - 2014-12-11 13:24 +1100
Re: When do default parameters get their values set? Rustom Mody <rustompmody@gmail.com> - 2014-12-10 18:50 -0800
Re: When do default parameters get their values set? Steven D'Aprano <steve@pearwood.info> - 2014-12-11 03:15 +0000
Re: When do default parameters get their values set? Rustom Mody <rustompmody@gmail.com> - 2014-12-10 19:26 -0800
Re: When do default parameters get their values set? Ben Finney <ben+python@benfinney.id.au> - 2014-12-11 14:49 +1100
Re: When do default parameters get their values set? Chris Kaynor <ckaynor@zindagigames.com> - 2014-12-11 09:10 -0800
Re: When do default parameters get their values set? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-12-12 09:51 +1100
Re: When do default parameters get their values set? random832@fastmail.us - 2014-12-11 15:44 -0500
Re: When do default parameters get their values set? "Tim Chase" <tim.chase@1:249/999.remove-cdt-this> - 2014-12-09 11:32 -0500
| From | "bSneddon" <bsneddon@1:249/999.remove-cdt-this> |
|---|---|
| Date | 2014-12-09 11:32 -0500 |
| Subject | When do default parameters get their values set? |
| Message-ID | <54866F2E.1765.complang@piz.noip.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
--- SoupGate-Win32 v1.05
* Origin: <SpaceSST.BBS.Fidonet<>NNTP.gateway.@.piz.noip.me> (1:249/999)
--- Synchronet 3.15b-Win32 NewsLink 1.92
SpaceSST BBS Usenet <> Fidonet Gateway
[toc] | [next] | [standalone]
| From | "Chris Angelico" <chris.angelico@1:249/999.remove-cdt-this> |
|---|---|
| Date | 2014-12-09 11:32 -0500 |
| Message-ID | <54866F2E.1767.complang@piz.noip.com> |
| In reply to | #82227 |
To: bSneddon
Copy: python-list@python.org (python-list@python.org)
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
--- SoupGate-Win32 v1.05
* Origin: <SpaceSST.BBS.Fidonet<>NNTP.gateway.@.piz.noip.me> (1:249/999)
--- Synchronet 3.15b-Win32 NewsLink 1.92
SpaceSST BBS Usenet <> Fidonet Gateway
[toc] | [prev] | [next] | [standalone]
| From | "Dave Angel" <dave.angel@1:249/999.remove-cdt-this> |
|---|---|
| Date | 2014-12-09 11:32 -0500 |
| Message-ID | <54866F2E.1768.complang@piz.noip.com> |
| In reply to | #82227 |
To: bSneddon
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
--- SoupGate-Win32 v1.05
* Origin: <SpaceSST.BBS.Fidonet<>NNTP.gateway.@.piz.noip.me> (1:249/999)
--- Synchronet 3.15b-Win32 NewsLink 1.92
SpaceSST BBS Usenet <> Fidonet Gateway
[toc] | [prev] | [next] | [standalone]
| From | Duncan Booth <duncan.booth@invalid.invalid> |
|---|---|
| Date | 2014-12-09 21:18 +0000 |
| Message-ID | <XnsA3FED89759430duncanbooth@127.0.0.1> |
| In reply to | #82230 |
"Dave Angel" <dave.angel@1:249/999.remove-cdt-this> wrote: > 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. The function is compiled when the module is compiled. At latest that is when the module is imported (though in most cases it was probably compiled the first time you ran the code and isn't recompiled unless the source code changes). The default parameters are actually evaluated when the 'def' statement is executed and the function object is created from the default arguments and the previously compiled code block. -- Duncan Booth http://kupuguy.blogspot.com
[toc] | [prev] | [next] | [standalone]
| From | random832@fastmail.us |
|---|---|
| Date | 2014-12-09 18:07 -0500 |
| Message-ID | <mailman.16782.1418166477.18130.python-list@python.org> |
| In reply to | #82240 |
On Tue, Dec 9, 2014, at 16:18, Duncan Booth wrote:
> The default parameters are actually evaluated when the 'def' statement is
> executed and the function object is created from the default arguments
> and
> the previously compiled code block.
Which means that if you execute the def statement [or lambda] more than
once, you will get more than one instance of the default parameter.
>>> def f(): return (lambda x={}: x)
...
>>> f()() is f()()
False
>>> g = f()
>>> g() is g()
True
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-12-09 18:44 -0800 |
| Message-ID | <bc561515-fe9d-41c1-bdda-7362e76aecdf@googlegroups.com> |
| In reply to | #82242 |
On Wednesday, December 10, 2014 4:38:18 AM UTC+5:30, rand...@fastmail.us wrote:
> On Tue, Dec 9, 2014, at 16:18, Duncan Booth wrote:
> > The default parameters are actually evaluated when the 'def' statement is
> > executed and the function object is created from the default arguments
> > and
> > the previously compiled code block.
>
> Which means that if you execute the def statement [or lambda] more than
> once, you will get more than one instance of the default parameter.
>
> >>> def f(): return (lambda x={}: x)
> ...
> >>> f()() is f()()
> False
> >>> g = f()
> >>> g() is g()
> True
Nice example -- thanks.
Elaborates the why of this gotcha -- a def(inition) is imperative.
From a semantic pov very clean.
From an expectation pov always surprising.
[toc] | [prev] | [next] | [standalone]
| From | random832@fastmail.us |
|---|---|
| Date | 2014-12-10 13:38 -0500 |
| Message-ID | <mailman.16824.1418236733.18130.python-list@python.org> |
| In reply to | #82252 |
On Tue, Dec 9, 2014, at 21:44, Rustom Mody wrote:
> Nice example -- thanks.
> Elaborates the why of this gotcha -- a def(inition) is imperative.
> From a semantic pov very clean.
> From an expectation pov always surprising.
Of course, I used a lambda for this. The equivalent without would be:
def f():
def g(x={}):
return x
return g
Ultimately it's no different from when any non-immutable expression is
executed.
def f: return {'x': {}}
f()['x'] is f()['x'] # False
d = f()
d['x'] is d['x'] # True
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-12-10 18:18 -0800 |
| Message-ID | <c0d4cdaf-6d71-43ae-a998-d422fe4ecf0e@googlegroups.com> |
| In reply to | #82305 |
On Thursday, December 11, 2014 12:09:10 AM UTC+5:30, rand...@fastmail.us wrote:
> On Tue, Dec 9, 2014, at 21:44, Rustom Mody wrote:
> > Nice example -- thanks.
> > Elaborates the why of this gotcha -- a def(inition) is imperative.
> > From a semantic pov very clean.
> > From an expectation pov always surprising.
>
> Of course, I used a lambda for this. The equivalent without would be:
>
> def f():
> def g(x={}):
> return x
> return g
Ok. As I wrote in the "Question on lambdas" thread yesterday
lambdas and defs are equivalent
And going the other way -- no defs only lambdas its this:
>>> f = lambda : (lambda x= {}: x)
>>> f()() is f()()
False
>>> d = f()
>>> d() is d()
True
>>>
But I have a different question -- can this be demonstrated without the 'is'?
Because to me 'is' -- equivalently id -- is a code-smell and is like
explaining funny behavior by showing the dis -- like
$ gcc -S ...
-- output.
It can always explain, but indicates that the semantics is not (sufficiently) abstract in this aspect
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-12-11 13:24 +1100 |
| Message-ID | <mailman.16834.1418264648.18130.python-list@python.org> |
| In reply to | #82321 |
On Thu, Dec 11, 2014 at 1:18 PM, Rustom Mody <rustompmody@gmail.com> wrote: > But I have a different question -- can this be demonstrated without the 'is'? > Because to me 'is' -- equivalently id -- is a code-smell and is like > explaining funny behavior by showing the dis -- like > $ gcc -S ... > -- output. > > It can always explain, but indicates that the semantics is not (sufficiently) abstract in this aspect Not so. Object identity is a fundamental part of Python. Indistinguishable-but-distinct mutable objects are crucial to Python's behaviour. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-12-10 18:50 -0800 |
| Message-ID | <17ff7b91-77cd-4660-a7ee-c9a1d512b06c@googlegroups.com> |
| In reply to | #82322 |
On Thursday, December 11, 2014 8:05:13 AM UTC+5:30, Chris Angelico wrote: > On Thu, Dec 11, 2014 at 1:18 PM, Rustom Mody wrote: > > But I have a different question -- can this be demonstrated without the 'is'? > > Because to me 'is' -- equivalently id -- is a code-smell and is like > > explaining funny behavior by showing the dis -- like > > $ gcc -S ... > > -- output. > > > > It can always explain, but indicates that the semantics is not (sufficiently) abstract in this aspect > > Not so. Object identity is a fundamental part of Python. > Indistinguishable-but-distinct mutable objects are crucial to Python's > behaviour. You are saying much the same as I am. Most programmers try to write programs without gotos. Good (C) programmers know that 1. gotos can be more efficient than 'structured' code 2. And even sometimes more elegant -- think of coding a non-trivial automaton with State=Label, Transition=goto Still most (reasonable) C-programmers will at least try to write goto-less code. Analogously here: 'is/id' are part of python. Nevertheless *explaining* something with and without these are significantly different. Naturally we may have different feelings about 'is' in python. However 'agree/disagree' is (in my book) a verb that is applied to facts not feelings :-)
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2014-12-11 03:15 +0000 |
| Message-ID | <54890c3d$0$2817$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #82321 |
On Wed, 10 Dec 2014 18:18:44 -0800, Rustom Mody wrote:
> And going the other way -- no defs only lambdas its this:
>
>
>>>> f = lambda : (lambda x= {}: x)
>>>> f()() is f()()
> False
>>>> d = f()
>>>> d() is d()
> True
>>>>
>>>>
>
> But I have a different question -- can this be demonstrated without the
> 'is'?
Can *what* be demonstrated? That the functions returned are different
objects, or that the dicts are different objects? Both? Something else?
Using "is" you are demonstrating that calling the function twice returns
two distinct objects. That is the purpose of "is", to compare object
identity. Without "is", you can compare object IDs directly:
id(f()()) == id(f()())
but that's ugly and less efficient. Using "is" is the more idiomatic and
natural way to do this.
Other than that, you could do something to demonstrate the consequences
of the two values being distinct objects:
a = f()() # Call twice to get a dict.
b = f()()
a['key'] = 23
b['key'] # raises KeyError
or
a = f() # Call once to get a function.
b = f()
a.attribute = 23
b.attribute # raises AttributeError
Or you could inspect the byte-code of f and try to understand it.
> Because to me 'is' -- equivalently id -- is a code-smell
It is only a code-smell in the sense that caring about object identity
should be rare.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-12-10 19:26 -0800 |
| Message-ID | <e7f6710e-1d5c-4bcb-b7b0-56c6633f97eb@googlegroups.com> |
| In reply to | #82327 |
On Thursday, December 11, 2014 8:45:22 AM UTC+5:30, Steven D'Aprano wrote:
> On Wed, 10 Dec 2014 18:18:44 -0800, Rustom Mody wrote:
>
>
> > And going the other way -- no defs only lambdas its this:
> >
> >
> >>>> f = lambda : (lambda x= {}: x)
> >>>> f()() is f()()
> > False
> >>>> d = f()
> >>>> d() is d()
> > True
> >>>>
> >>>>
> >
> > But I have a different question -- can this be demonstrated without the
> > 'is'?
>
>
> Can *what* be demonstrated? That the functions returned are different
> objects, or that the dicts are different objects? Both? Something else?
What? Referential transparency (or the lack of it)
https://en.wikipedia.org/wiki/Referential_transparency_%28computer_science%29
Or if you like it more technical:
Python breaks referential transparency even in the absence of assignment
[From my (cursory) reading of the wikipedia page all the
no-transparent examples need assignment (or IO) to demo the point]
>
> Using "is" you are demonstrating that calling the function twice returns
> two distinct objects. That is the purpose of "is", to compare object
> identity. Without "is", you can compare object IDs directly:
>
> id(f()()) == id(f()())
>
> but that's ugly and less efficient. Using "is" is the more idiomatic and
> natural way to do this.
>
>
> Other than that, you could do something to demonstrate the consequences
> of the two values being distinct objects:
>
> a = f()() # Call twice to get a dict.
> b = f()()
> a['key'] = 23
> b['key'] # raises KeyError
>
>
> or
>
> a = f() # Call once to get a function.
> b = f()
> a.attribute = 23
> b.attribute # raises AttributeError
>
>
> Or you could inspect the byte-code of f and try to understand it.
>
>
>
> > Because to me 'is' -- equivalently id -- is a code-smell
>
> It is only a code-smell in the sense that caring about object identity
> should be rare.
Yes. Its good we agree on that ;-)
In the FP world referential opaqueness is the name of the devil.
In the more 'real' imperative/OO world there's way too much of it.
Finding a middle-way remains an IMHO important open problem
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2014-12-11 14:49 +1100 |
| Message-ID | <mailman.16837.1418269795.18130.python-list@python.org> |
| In reply to | #82328 |
Rustom Mody <rustompmody@gmail.com> writes: > In the FP world referential opaqueness is the name of the devil. Caring about object identity is not the same as referential opacity. > In the more 'real' imperative/OO world there's way too much of it. I'm very glad to be programming in the real world; there is more achievement in solving problems here. -- \ “The power of accurate observation is frequently called | `\ cynicism by those who don't have it.” —George Bernard Shaw | _o__) | Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Chris Kaynor <ckaynor@zindagigames.com> |
|---|---|
| Date | 2014-12-11 09:10 -0800 |
| Message-ID | <mailman.16858.1418317880.18130.python-list@python.org> |
| In reply to | #82327 |
[Multipart message — attachments visible in raw view] — view raw
On Wed, Dec 10, 2014 at 7:15 PM, Steven D'Aprano <steve@pearwood.info>
wrote:
> On Wed, 10 Dec 2014 18:18:44 -0800, Rustom Mody wrote:
>
>
> > And going the other way -- no defs only lambdas its this:
> >
> >
> >>>> f = lambda : (lambda x= {}: x)
> >>>> f()() is f()()
> > False
> >>>> d = f()
> >>>> d() is d()
> > True
> >>>>
> >>>>
> >
> > But I have a different question -- can this be demonstrated without the
> > 'is'?
>
>
> Can *what* be demonstrated? That the functions returned are different
> objects, or that the dicts are different objects? Both? Something else?
>
> Using "is" you are demonstrating that calling the function twice returns
> two distinct objects. That is the purpose of "is", to compare object
> identity. Without "is", you can compare object IDs directly:
>
> id(f()()) == id(f()())
>
> but that's ugly and less efficient. Using "is" is the more idiomatic and
> natural way to do this.
>
In CPython, that does not work, as the dictionary will be garbage collected
after each call to id:
>>> f = lambda : (lambda x= {}: x)
>>> f()() is f()()
False
>>> id(f()()) == id(f()())
True
>
> Other than that, you could do something to demonstrate the consequences
> of the two values being distinct objects:
>
> a = f()() # Call twice to get a dict.
> b = f()()
> a['key'] = 23
> b['key'] # raises KeyError
>
>
> or
>
> a = f() # Call once to get a function.
> b = f()
> a.attribute = 23
> b.attribute # raises AttributeError
>
>
> Or you could inspect the byte-code of f and try to understand it.
>
>
Another way would be to to demonstrate the behavior, without using is,
would be to use a global counter variable:
a = 1
def f():
global a
def g(b=[a]):
return b
a += 1
return g
>>> f()()
[1]
>>> f()()
[2]
>>> a = f()
>>> a()
[3]
>>> a()
[3]
>>> b = f()
>>> b()
[4]
>>> a()
[3]
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-12-12 09:51 +1100 |
| Message-ID | <548a1fd5$0$12996$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #82366 |
Chris Kaynor wrote:
> On Wed, Dec 10, 2014 at 7:15 PM, Steven D'Aprano <steve@pearwood.info>
> wrote:
>> Using "is" you are demonstrating that calling the function twice returns
>> two distinct objects. That is the purpose of "is", to compare object
>> identity. Without "is", you can compare object IDs directly:
>>
>> id(f()()) == id(f()())
>>
>> but that's ugly and less efficient. Using "is" is the more idiomatic and
>> natural way to do this.
>>
>
> In CPython, that does not work, as the dictionary will be garbage
> collected after each call to id:
>>>> f = lambda : (lambda x= {}: x)
>>>> f()() is f()()
> False
>>>> id(f()()) == id(f()())
> True
Nice catch! Thank you for the correction.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | random832@fastmail.us |
|---|---|
| Date | 2014-12-11 15:44 -0500 |
| Message-ID | <mailman.16870.1418330670.18130.python-list@python.org> |
| In reply to | #82321 |
On Wed, Dec 10, 2014, at 21:18, Rustom Mody wrote: > But I have a different question -- can this be demonstrated without the > 'is'? Er, yeah. You can, for example, add an item to one of the dictionaries and observe that it's not present in the other.
[toc] | [prev] | [next] | [standalone]
| From | "Tim Chase" <tim.chase@1:249/999.remove-cdt-this> |
|---|---|
| Date | 2014-12-09 11:32 -0500 |
| Message-ID | <54866F2E.1769.complang@piz.noip.com> |
| In reply to | #82227 |
To: bSneddon
Copy: python-list@python.org
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
--- SoupGate-Win32 v1.05
* Origin: <SpaceSST.BBS.Fidonet<>NNTP.gateway.@.piz.noip.me> (1:249/999)
--- Synchronet 3.15b-Win32 NewsLink 1.92
SpaceSST BBS Usenet <> Fidonet Gateway
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web