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


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

what does 'a=b=c=[]' do

Started byEric <einazaki668@yahoo.com>
First post2011-12-21 14:25 -0800
Last post2011-12-24 19:49 +0100
Articles 16 on this page of 56 — 18 participants

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


Contents

  what does 'a=b=c=[]' do Eric <einazaki668@yahoo.com> - 2011-12-21 14:25 -0800
    Re: what does 'a=b=c=[]' do Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2011-12-21 18:20 -0500
      Re: what does 'a=b=c=[]' do Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-21 23:48 +0000
        Re: what does 'a=b=c=[]' do Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-12-24 19:41 +0100
          Re: what does 'a=b=c=[]' do Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-25 13:16 +0000
      Re: what does 'a=b=c=[]' do Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-12-24 19:45 +0100
    Re: what does 'a=b=c=[]' do Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-21 23:44 +0000
      Re: what does 'a=b=c=[]' do Eric <einazaki668@yahoo.com> - 2011-12-22 20:27 -0800
    Re: what does 'a=b=c=[]' do alex23 <wuwei23@gmail.com> - 2011-12-21 16:50 -0800
      Re: what does 'a=b=c=[]' do Rolf Camps <rolf@roce.be> - 2011-12-22 09:51 +0100
        Re: what does 'a=b=c=[]' do alex23 <wuwei23@gmail.com> - 2011-12-22 18:10 -0800
          Re: what does 'a=b=c=[]' do Ian Kelly <ian.g.kelly@gmail.com> - 2011-12-22 19:59 -0700
            Re: what does 'a=b=c=[]' do alex23 <wuwei23@gmail.com> - 2011-12-22 19:40 -0800
              Re: what does 'a=b=c=[]' do Chris Angelico <rosuav@gmail.com> - 2011-12-23 15:25 +1100
              Re: what does 'a=b=c=[]' do Ian Kelly <ian.g.kelly@gmail.com> - 2011-12-22 22:22 -0700
                Re: what does 'a=b=c=[]' do alex23 <wuwei23@gmail.com> - 2011-12-22 22:00 -0800
          Re: what does 'a=b=c=[]' do rusi <rustompmody@gmail.com> - 2011-12-23 00:38 -0800
            Re: what does 'a=b=c=[]' do Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-23 09:39 +0000
              Re: what does 'a=b=c=[]' do rusi <rustompmody@gmail.com> - 2011-12-23 02:22 -0800
                Re: what does 'a=b=c=[]' do Robert Kern <robert.kern@gmail.com> - 2011-12-23 13:10 +0000
                  Re: what does 'a=b=c=[]' do rusi <rustompmody@gmail.com> - 2011-12-23 05:23 -0800
                    Re: what does 'a=b=c=[]' do Robert Kern <robert.kern@gmail.com> - 2011-12-23 13:53 +0000
                      Re: what does 'a=b=c=[]' do rusi <rustompmody@gmail.com> - 2011-12-23 06:57 -0800
                        Re: what does 'a=b=c=[]' do Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-23 15:33 +0000
                          Re: what does 'a=b=c=[]' do rusi <rustompmody@gmail.com> - 2011-12-23 07:59 -0800
            Re: what does 'a=b=c=[]' do Ethan Furman <ethan@stoneleaf.us> - 2011-12-23 00:49 -0800
            Re: what does 'a=b=c=[]' do Chris Angelico <rosuav@gmail.com> - 2011-12-23 20:59 +1100
              Re: what does 'a=b=c=[]' do rusi <rustompmody@gmail.com> - 2011-12-23 02:31 -0800
                Timeout when calling COM objects on Windows Wong Wah Meng-R32813 <r32813@freescale.com> - 2011-12-23 11:20 +0000
                Re: what does 'a=b=c=[]' do Michael Torrie <torriem@gmail.com> - 2011-12-23 10:23 -0700
              Re: what does 'a=b=c=[]' do Neil Cerutti <neilc@norwich.edu> - 2011-12-23 13:10 +0000
                Re: what does 'a=b=c=[]' do Neil Cerutti <neilc@norwich.edu> - 2011-12-23 13:13 +0000
                  Early and late binding [was Re: what does 'a=b=c=[]' do] Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-23 15:49 +0000
                    Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Chris Angelico <rosuav@gmail.com> - 2011-12-24 02:55 +1100
                      Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-23 22:32 +0000
                        Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Chris Angelico <rosuav@gmail.com> - 2011-12-24 09:50 +1100
                          Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-24 08:11 +0000
                    Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Roy Smith <roy@panix.com> - 2011-12-23 11:15 -0500
                      Re: Early and late binding [was Re: what does 'a=b=c=[]' do] alex23 <wuwei23@gmail.com> - 2011-12-24 05:43 -0800
                    Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Mel Wilson <mwilson@the-wire.com> - 2011-12-23 11:27 -0500
                      Re: Early and late binding [was Re: what does 'a=b=c=[]' do] alex23 <wuwei23@gmail.com> - 2011-12-24 05:52 -0800
                    Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Neil Cerutti <neilc@norwich.edu> - 2011-12-23 17:03 +0000
                      Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-24 08:25 +0000
                        Re: Early and late binding [was Re: what does 'a=b=c=[]' do] alex23 <wuwei23@gmail.com> - 2011-12-24 06:08 -0800
                          Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Devin Jeanpierre <jeanpierreda@gmail.com> - 2011-12-24 18:25 -0500
                            Re: Early and late binding [was Re: what does 'a=b=c=[]' do] alex23 <wuwei23@gmail.com> - 2011-12-24 16:10 -0800
                              Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Devin Jeanpierre <jeanpierreda@gmail.com> - 2011-12-24 19:32 -0500
                                Re: Early and late binding [was Re: what does 'a=b=c=[]' do] rusi <rustompmody@gmail.com> - 2011-12-24 19:22 -0800
                        Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Lie Ryan <lie.1296@gmail.com> - 2011-12-25 15:12 +1100
                    Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Devin Jeanpierre <jeanpierreda@gmail.com> - 2011-12-23 19:24 -0500
                      Re: Early and late binding [was Re: what does 'a=b=c=[]' do] Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-24 08:26 +0000
          Re: what does 'a=b=c=[]' do Ethan Furman <ethan@stoneleaf.us> - 2011-12-23 00:38 -0800
      Re: what does 'a=b=c=[]' do Ethan Furman <ethan@stoneleaf.us> - 2011-12-22 05:20 -0800
      Re: what does 'a=b=c=[]' do Eric <einazaki668@yahoo.com> - 2011-12-22 19:46 -0800
    Re: what does 'a=b=c=[]' do Lie Ryan <lie.1296@gmail.com> - 2011-12-24 21:30 +1100
    Re: what does 'a=b=c=[]' do Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-12-24 19:49 +0100

Page 3 of 3 — ← Prev page 1 2 [3]


#17839 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

Fromalex23 <wuwei23@gmail.com>
Date2011-12-24 05:52 -0800
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<0fea2ea6-80df-42c4-8fbb-5b4314095672@h37g2000pri.googlegroups.com>
In reply to#17814
On Dec 24, 2:27 am, Mel Wilson <mwil...@the-wire.com> wrote:
> In a tool that's meant for other people to use to accomplish work of their
> own, breaking workflow is a cardinal sin.
>
> In a research language that's meant always to be up-to-date with the concept
> of the week, not so much.

What on earth gave you the impression Python was bleeding edge? As
there's more to the language than its syntax, "breaking workflow"
disrupts the core library as much as it does the code of everyone
else.

More importantly, you're talking pap. Research is as much about
communication as programming; if you expect every single researcher in
a discipline (or even in the same _building_) to remain in perfect
lockstep with the version releases of a domain-relevant language,
you're either not a researcher or not a very good one. You should get
out to a conference occasionally and see what people think about your
"concept of the week" idea.

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


#17817 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

FromNeil Cerutti <neilc@norwich.edu>
Date2011-12-23 17:03 +0000
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<9ljqifFfj9U3@mid.individual.net>
In reply to#17807
On 2011-12-23, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
> On Fri, 23 Dec 2011 13:13:38 +0000, Neil Cerutti wrote:
>> On 2011-12-23, Neil Cerutti <neilc@norwich.edu> wrote:
>>> Is the misfeature that Python doesn't evaluate the default
>>> argument expression every time you call the function? What
>>> would be the harm if it did?
>> 
>> ...you know, assuming it wouldn't break existing code. ;)
>
> It will. Python's default argument strategy has been in use for
> 20 years. Some code will rely on it. I know mine does.

I'm aware of that. I should have put the question differently,
but you did guess what I meant to ask. Thanks for the dicussion.

> Early binding is simple to implement and simple to explain:
> when you define a function, the default value is evaluated
> once, and the result stored to be used whenever it is needed.
> The disadvantage is that it can lead to unexpected results for
> mutable arguments.
>
> Late binding is also simple to explain, but a little harder to
> implement. The function needs to store the default value as a
> piece of code (an expression) which can be re-evaluated as
> often as needed, not an object.
>
> The disadvantage of late binding is that since the expression
> is live, it needs to be calculated each time, even if it turns
> out to be the same result. But there's no guarantee that it
> will return the same result each time: 

That's its main *advantage*.

> consider a default value like x=time.time(), which will return
> a different value each time it is called; or one like x=a+b,
> which will vary if either a or b are changed. Or will fail
> altogether if either a or b are deleted. This will surprise
> some people some of the time and lead to demands that Python
> "fix" the "obviously buggy" default argument gotcha.

It's hard to see anyone being confused by the resultant
exception. It's much harder to figure out what's going wrong with
an early-bound mutable.

> If a language only offers one, I maintain it should offer early
> binding (the status quo). Why? Because it is more elegant to
> fake late binding in an early binding language than vice versa.
>
> To fake late binding in a language with early binding, use a
> sentinel value and put the default value inside the body of the
> function:
>
>     def func(x, y=None):
>         if y is None:
>             y = []
>         ...
>
> All the important parts of the function are in one place,
> namely inside the function.
>
> To fake early binding when the language provides late binding,
> you still use a sentinel value, but the initialization code
> creating the default value is outside the body of the function,
> usually in a global variable:
>
>     _DEFAULT_Y = []  # Private constant, don't touch.
>
>     def func(x, y=None):
>         if y is None:
>             y = _DEFAULT_Y
>         ...
>
> This separates parts of the code that should be together, and
> relies on a global, with all the disadvantages that implies.

I'd use a function attribute.

def func(x, y=None):
  if y is None:
    y = func.default_y
  ...
func.default_y = []

That's awkward only if you believe function attributes are
awkward. Even if common practice were instead to use a global
variable, as you did, it wouldn't be considered bad if it were a
common idiom. In case, a global that's not meant to be rebound or
mutated is the best possible variety.

However, I also wouldn't base the decision of late versus early
binding on how confusing it would be if you assume wrongly which
one you are getting. Most default function arguments are
literals, so in Python the question just doesn't come up until
you get mutabled.

The greater efficiency was probably what decided this question
for Python, right? Since late-binding is so easy to fake, is
hardly ever what you want, and would make all code slower, why do
it?

-- 
Neil Cerutti

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


#17836 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-12-24 08:25 +0000
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<4ef58c60$0$29973$c3e8da3$5496439d@news.astraweb.com>
In reply to#17817
On Fri, 23 Dec 2011 17:03:11 +0000, Neil Cerutti wrote:

>> The disadvantage of late binding is that since the expression is live,
>> it needs to be calculated each time, even if it turns out to be the
>> same result. But there's no guarantee that it will return the same
>> result each time:
> 
> That's its main *advantage*.

Ah yes, sorry, poor wording on my part. Whether calculating the default 
value *once* or *each time* is an advantage or disadvantage depends on 
what you're trying to do. Either way, it could be just what you want, or 
an annoying source of bugs.


>> consider a default value like x=time.time(), which will return a
>> different value each time it is called; or one like x=a+b, which will
>> vary if either a or b are changed. Or will fail altogether if either a
>> or b are deleted. This will surprise some people some of the time and
>> lead to demands that Python "fix" the "obviously buggy" default
>> argument gotcha.
> 
> It's hard to see anyone being confused by the resultant exception.

That's because you're coming at it from the perspective of somebody who 
knows what to expect, in the middle of a discussion about the semantics 
of late binding. Now imagine you're a newbie who has never thought about 
the details of when the default value is created, but has a function like 
"def foo(x, y=a+b)". He calls foo(x) seven times and it works, and on the 
eighth time it blows up, perhaps with a NameError. It's surprising 
behaviour, and newbies aren't good at diagnosing surprising bugs.

Or worse, it doesn't blow up at all, but gives some invalid value that 
causes your calculations to be completely wrong. Exceptions are not the 
worst bug to have -- they are the best.


> It's
> much harder to figure out what's going wrong with an early-bound
> mutable.

Only for those who don't understand, or aren't thinking about, Python's 
object model. The behaviour of early-bound mutables is obvious and clear 
once you think about it, but it does require you to think about what's 
going on under the hood, so to speak.

[...]
>> To fake early binding when the language provides late binding, you
>> still use a sentinel value, but the initialization code creating the
>> default value is outside the body of the function, usually in a global
>> variable:
[...]
 
> I'd use a function attribute.
> 
> def func(x, y=None):
>   if y is None:
>     y = func.default_y
>   ...
> func.default_y = []
> 
> That's awkward only if you believe function attributes are awkward.

I do. All you've done is move the default from *before* the function is 
defined to *after* the function is defined, instead of keeping it in the 
function definition. It's still separate, and if the function is renamed 
your code stops working. In other words, it violates encapsulation of the 
function.

That's not to say that you shouldn't do this. It's a perfectly reasonable 
technique, and I've used it myself, but it's not as elegant as the 
current Python default argument behaviour.


[...]
> The greater efficiency was probably what decided this question for
> Python, right? Since late-binding is so easy to fake, is hardly ever
> what you want, and would make all code slower, why do it?

Excellent point.


-- 
Steven

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


#17841 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

Fromalex23 <wuwei23@gmail.com>
Date2011-12-24 06:08 -0800
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<ca6d1ce1-da00-4bef-b43f-f6374d77280c@24g2000prd.googlegroups.com>
In reply to#17836
On Dec 24, 6:25 pm, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:
> > It's
> > much harder to figure out what's going wrong with an early-bound
> > mutable.
>
> Only for those who don't understand, or aren't thinking about, Python's
> object model. The behaviour of early-bound mutables is obvious and clear
> once you think about it, but it does require you to think about what's
> going on under the hood, so to speak.

And here we've come full circle to the point of this thread.

If Python was ever 'fixed' to prevent this issue, I'm pretty sure we'd
see an increase in the number of questions like the OP's.

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


#17866 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

FromDevin Jeanpierre <jeanpierreda@gmail.com>
Date2011-12-24 18:25 -0500
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<mailman.4055.1324769169.27778.python-list@python.org>
In reply to#17841
> If Python was ever 'fixed' to prevent this issue, I'm pretty sure we'd
> see an increase in the number of questions like the OP's.

What makes you so sure? Both models do make sense and are equally
valid, it's just that only one of them is true. Is it just because
people already used to Python would get confused?

-- Devin

On Sat, Dec 24, 2011 at 9:08 AM, alex23 <wuwei23@gmail.com> wrote:
> On Dec 24, 6:25 pm, Steven D'Aprano <steve
> +comp.lang.pyt...@pearwood.info> wrote:
>> > It's
>> > much harder to figure out what's going wrong with an early-bound
>> > mutable.
>>
>> Only for those who don't understand, or aren't thinking about, Python's
>> object model. The behaviour of early-bound mutables is obvious and clear
>> once you think about it, but it does require you to think about what's
>> going on under the hood, so to speak.
>
> And here we've come full circle to the point of this thread.
>
> If Python was ever 'fixed' to prevent this issue, I'm pretty sure we'd
> see an increase in the number of questions like the OP's.
> --
> http://mail.python.org/mailman/listinfo/python-list

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


#17867 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

Fromalex23 <wuwei23@gmail.com>
Date2011-12-24 16:10 -0800
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<f6c4dcdb-4092-4c44-8a82-234213fde6da@a31g2000pre.googlegroups.com>
In reply to#17866
On Dec 25, 9:25 am, Devin Jeanpierre <jeanpierr...@gmail.com> wrote:
> > If Python was ever 'fixed' to prevent this issue, I'm pretty sure we'd
> > see an increase in the number of questions like the OP's.
>
> What makes you so sure? Both models do make sense and are equally
> valid, it's just that only one of them is true. Is it just because
> people already used to Python would get confused?

Because I believe that the source of confusion has far more to do with
mutable/immutable objects than with early/late binding. Masking or
'correcting' an aspect of Python's behaviour because novices make the
wrong assumption about it just pushes the problem elsewhere and
potentially makes the language inconsistent at the same time.

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


#17870 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

FromDevin Jeanpierre <jeanpierreda@gmail.com>
Date2011-12-24 19:32 -0500
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<mailman.4056.1324773177.27778.python-list@python.org>
In reply to#17867
> Because I believe that the source of confusion has far more to do with
> mutable/immutable objects than with early/late binding. Masking or
> 'correcting' an aspect of Python's behaviour because novices make the
> wrong assumption about it just pushes the problem elsewhere and
> potentially makes the language inconsistent at the same time.

That seems fairly silly -- foo.append(bar) obviously mutates
_something_ . Certainly it wasn't the source of my confusion when I
got caught on this. What makes you believe that the fundamental
confusion is about mutability?

(Also, if the change is applied everywhere, the language would not be
inconsistent.)

-- Devin

On Sat, Dec 24, 2011 at 7:10 PM, alex23 <wuwei23@gmail.com> wrote:
> On Dec 25, 9:25 am, Devin Jeanpierre <jeanpierr...@gmail.com> wrote:
>> > If Python was ever 'fixed' to prevent this issue, I'm pretty sure we'd
>> > see an increase in the number of questions like the OP's.
>>
>> What makes you so sure? Both models do make sense and are equally
>> valid, it's just that only one of them is true. Is it just because
>> people already used to Python would get confused?
>
> Because I believe that the source of confusion has far more to do with
> mutable/immutable objects than with early/late binding. Masking or
> 'correcting' an aspect of Python's behaviour because novices make the
> wrong assumption about it just pushes the problem elsewhere and
> potentially makes the language inconsistent at the same time.
> --
> http://mail.python.org/mailman/listinfo/python-list

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


#17875 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

Fromrusi <rustompmody@gmail.com>
Date2011-12-24 19:22 -0800
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<5198e7e2-859b-4894-8170-16ad35d67625@h7g2000prn.googlegroups.com>
In reply to#17870
On Dec 25, 5:32 am, Devin Jeanpierre <jeanpierr...@gmail.com> wrote:
> alex23 wrote:
> > Because I believe that the source of confusion has far more to do with
> > mutable/immutable objects than with early/late binding. Masking or
> > 'correcting' an aspect of Python's behaviour because novices make the
> > wrong assumption about it just pushes the problem elsewhere and
> > potentially makes the language inconsistent at the same time.

Thats hitting the nail on the head.

>
> That seems fairly silly -- foo.append(bar) obviously mutates
> _something_ . Certainly it wasn't the source of my confusion when I
> got caught on this. What makes you believe that the fundamental
> confusion is about mutability?

The confusion is not about mutability. Its about mutability and
parameter passing being non-orthogonal.

>
> (Also, if the change is applied everywhere, the language would not be
> inconsistent.)

Obviously that would depend on what the change is.

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


#17876 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

FromLie Ryan <lie.1296@gmail.com>
Date2011-12-25 15:12 +1100
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<mailman.4059.1324786507.27778.python-list@python.org>
In reply to#17836
On 12/24/2011 07:25 PM, Steven D'Aprano wrote:
>> I'd use a function attribute.
>>
>> def func(x, y=None):
>>    if y is None:
>>      y = func.default_y
>>    ...
>> func.default_y = []
>>
>> That's awkward only if you believe function attributes are awkward.
>
> I do. All you've done is move the default from *before* the function is
> defined to *after* the function is defined, instead of keeping it in the
> function definition. It's still separate, and if the function is renamed
> your code stops working. In other words, it violates encapsulation of the
> function.

Although we can solve that (default being after the function is defined) 
using a simple decorator:

def funcargs(**args):
     def __decorate_with_args(func):
         for k,v in args.items():
             setattr(func, k, v)
         return func
     return __decorate_with_args

Usage:

@funcargs(foo=4)
def bar(baz):
     return baz + bar.foo

et voila, we had just reinvented early binding default argument, with a 
much uglier syntax.

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


#17830 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

FromDevin Jeanpierre <jeanpierreda@gmail.com>
Date2011-12-23 19:24 -0500
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<mailman.4042.1324686335.27778.python-list@python.org>
In reply to#17807
> To fake early binding when the language provides late binding, you still
> use a sentinel value, but the initialization code creating the default
> value is outside the body of the function, usually in a global variable:
>
>    _DEFAULT_Y = []  # Private constant, don't touch.
>
>    def func(x, y=None):
>        if y is None:
>            y = _DEFAULT_Y
>        ...
>
> This separates parts of the code that should be together, and relies on a
> global, with all the disadvantages that implies.

No, you can just do def func(x, y=_DEFAULT_Y): ...

-- Devin

On Fri, Dec 23, 2011 at 10:49 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> On Fri, 23 Dec 2011 13:13:38 +0000, Neil Cerutti wrote:
>
>> On 2011-12-23, Neil Cerutti <neilc@norwich.edu> wrote:
>>> Is the misfeature that Python doesn't evaluate the default argument
>>> expression every time you call the function? What would be the harm if
>>> it did?
>>
>> ...you know, assuming it wouldn't break existing code. ;)
>
> It will. Python's default argument strategy has been in use for 20 years.
> Some code will rely on it. I know mine does.
>
> There are two strategies for dealing with default arguments that I know
> of: early binding and late binding. Python has early binding: the default
> argument is evaluated once, when the function is created. Late binding
> means the default argument is always re-evaluated each time it is needed.
>
> Both strategies are reasonable choices. Both have advantages and
> disadvantages. Both have use-cases, and both lead to confusion when the
> user expects one but gets the other. If you think changing from early to
> late binding will completely eliminate the default argument "gotcha", you
> haven't thought things through -- at best you might reduce the number of
> complaints, but only at the cost of shifting them from one set of use-
> cases to another.
>
> Early binding is simple to implement and simple to explain: when you
> define a function, the default value is evaluated once, and the result
> stored to be used whenever it is needed. The disadvantage is that it can
> lead to unexpected results for mutable arguments.
>
> Late binding is also simple to explain, but a little harder to implement.
> The function needs to store the default value as a piece of code (an
> expression) which can be re-evaluated as often as needed, not an object.
>
> The disadvantage of late binding is that since the expression is live, it
> needs to be calculated each time, even if it turns out to be the same
> result. But there's no guarantee that it will return the same result each
> time: consider a default value like x=time.time(), which will return a
> different value each time it is called; or one like x=a+b, which will
> vary if either a or b are changed. Or will fail altogether if either a or
> b are deleted. This will surprise some people some of the time and lead
> to demands that Python "fix" the "obviously buggy" default argument
> gotcha.
>
> If a language only offers one, I maintain it should offer early binding
> (the status quo). Why? Because it is more elegant to fake late binding in
> an early binding language than vice versa.
>
> To fake late binding in a language with early binding, use a sentinel
> value and put the default value inside the body of the function:
>
>    def func(x, y=None):
>        if y is None:
>            y = []
>        ...
>
> All the important parts of the function are in one place, namely inside
> the function.
>
> To fake early binding when the language provides late binding, you still
> use a sentinel value, but the initialization code creating the default
> value is outside the body of the function, usually in a global variable:
>
>    _DEFAULT_Y = []  # Private constant, don't touch.
>
>    def func(x, y=None):
>        if y is None:
>            y = _DEFAULT_Y
>        ...
>
> This separates parts of the code that should be together, and relies on a
> global, with all the disadvantages that implies.
>
>
>
> --
> Steven
> --
> http://mail.python.org/mailman/listinfo/python-list

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


#17837 — Re: Early and late binding [was Re: what does 'a=b=c=[]' do]

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-12-24 08:26 +0000
SubjectRe: Early and late binding [was Re: what does 'a=b=c=[]' do]
Message-ID<4ef58cd3$0$29973$c3e8da3$5496439d@news.astraweb.com>
In reply to#17830
On Fri, 23 Dec 2011 19:24:44 -0500, Devin Jeanpierre wrote:

>> To fake early binding when the language provides late binding, you
>> still use a sentinel value, but the initialization code creating the
>> default value is outside the body of the function, usually in a global
>> variable:
>>
>>    _DEFAULT_Y = []  # Private constant, don't touch.
>>
>>    def func(x, y=None):
>>        if y is None:
>>            y = _DEFAULT_Y
>>        ...
>>
>> This separates parts of the code that should be together, and relies on
>> a global, with all the disadvantages that implies.
> 
> No, you can just do def func(x, y=_DEFAULT_Y): ...

Point taken. Nevertheless, the semantics are still not the same as actual 
early binding: if the global name is deleted or changed, the function 
stops working.



-- 
Steven

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


#17784

FromEthan Furman <ethan@stoneleaf.us>
Date2011-12-23 00:38 -0800
Message-ID<mailman.4023.1324632904.27778.python-list@python.org>
In reply to#17766
Ian Kelly wrote:
> On Thu, Dec 22, 2011 at 7:10 PM, alex23 <wuwei23@gmail.com> wrote:
>> On Dec 22, 6:51 pm, Rolf Camps <r...@roce.be> wrote:
>>> I'm afraid it's dangerous to encourage the use of '[]' as assignment to
>>> a parameter in a function definition. If you use the function several
>>> times 'default' always points to the same list.
 >>
>> I appreciate the concern, but adding a default argument guard would
>> not only obscure the code. It's irrelevant, as you recognise, because
>> no matter what, it's going to make copies of the default argument.
> 
> It's only irrelevant in the immediate context of the code you posted.
> But when Joe Novice sees your code and likes it and duplicates it a
> million times without receiving any warning about it, he's eventually
> going to write a function that modifies its default list argument, and
> he'll be in for a nasty surprise when he does.

And then he will learn about it and not make the mistake again (or if he 
does, it take much less time to figure it out).

~Ethan~

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


#17733

FromEthan Furman <ethan@stoneleaf.us>
Date2011-12-22 05:20 -0800
Message-ID<mailman.3977.1324561916.27778.python-list@python.org>
In reply to#17711
Rolf Camps wrote:
> alex23 schreef op wo 21-12-2011 om 16:50 [-0800]:
>> I'd say that _is_ the most pythonic way, it's very obvious in its
>> intent (or would be with appropriate names). If it bothers you that
>> much:
>>
>>     def listgen(count, default=[]):
>>         for _ in xrange(count):
>>             yield default[:]
>>
>>     x, y, z = listgen(3)
>>
> I would change your function to (Python3.x):
> 
> 	def empty_lists(count):
> 	    for _ in range(count):
> 		yield []

While it's good to be careful, default mutable arguments have their 
place.  Alex's versioun allows one to use an already existing list and 
get shallow copies of it, yours will only create empty lists.

a, b, c = listgen([1, 2, 3])
# a, b, & c are bound to different lists

~Ethan~

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


#17770

FromEric <einazaki668@yahoo.com>
Date2011-12-22 19:46 -0800
Message-ID<1ec8f662-f4ef-4f99-b476-5e5ae2a3b412@p41g2000yqm.googlegroups.com>
In reply to#17711
On Dec 21, 6:50 pm, alex23 <wuwe...@gmail.com> wrote:
> On Dec 22, 8:25 am, Eric <einazaki...@yahoo.com> wrote:
>
> > This surprises me, can someone tell me why it shouldn't?  I figure if
> > I want to create and initialize three scalars the just do "a=b=c=7",
> > for example, so why not extend it to arrays.
>
> The thing to remember is that everything is an object, and that it's
> better to think of variables as labels on an object.
>
> So: a=b=c=7 means that _one_ integer object with the value of 7 can be
> referenced using any of the labels a, b or c. x=y=z=[] means that
> _one_ empty list can be referenced using x, y or z.
>
> The difference is that the value of a number object _cannot be
> changed_ ('immutable') while a list can be modified to add or remove
> items ('mutable'). a=10 just reassigns the label a to an integer
> object of value 10. x.append("foo") _modifies_ the list referred to by
> x, which is the same list known as y & z.
>


> > Also, is there a more pythonic way to do "x=[], y=[], z=[]"?
>
> I'd say that _is_ the most pythonic way, it's very obvious in its
> intent (or would be with appropriate names). If it bothers you that
> much:
>

Thanks for the explanation.  I guess from what I've seen of Python
so far I was expecting something more, I don't know, compact.
Anyway, it doesn't bother me, at least not enough to go and do
something like this:

>     def listgen(count, default=[]):
>         for _ in xrange(count):
>             yield default[:]
>
>     x, y, z = listgen(3)

Thanks,
eric

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


#17838

FromLie Ryan <lie.1296@gmail.com>
Date2011-12-24 21:30 +1100
Message-ID<mailman.4046.1324722625.27778.python-list@python.org>
In reply to#17707
On 12/22/2011 10:20 AM, Dennis Lee Bieber wrote:

> which is to define the names "a", "b", and "c", and connects the three
> names to the single object (integer 7 or new empty list).

note that this "connects" and "disconnecting" business is more commonly 
referred to in python parlance as "binding" a name to an object.

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


#17858

FromThomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de>
Date2011-12-24 19:49 +0100
Message-ID<jd53c8$om1$1@r03.glglgl.gl>
In reply to#17707
Am 21.12.2011 23:25 schrieb Eric:

> Is it true that if I want to create an array or arbitrary size such
> as:
>     for a in range(n):
>        x.append(<some function...>)
>
> I must do this instead?
>     x=[]
>     for a in range(n):
>        x.append(<some function...>)

Of course - your x must exist before using it.

 > Now to my actual question.  I need to do the above for multiple arrays
> (all the same, arbitrary size).  So I do this:
>     x=y=z=[]
>     for a in range(n):
>        x.append(<some function...>)
>        y.append(<some other function...>)
>        z.append(<yet another function...>)
> Also, is there a more pythonic way to do "x=[], y=[], z=[]"?

You could do:

def create_xyz(n):
     for a in range(n):
         yield <some function...>, <some other function...>, \
		<yet another function...>)

x, y, z = zip(*create_xyz(11))

or, if you want x, y, z to be lists,

x, y, z = [list(i) for i in zip(*create_xyz(11))]

.


Thomas

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

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


csiph-web