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


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

Evaluation order

Started bycandide <c.candide@laposte.net>
First post2015-07-09 17:10 -0700
Last post2015-07-10 15:49 +0100
Articles 8 — 5 participants

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


Contents

  Evaluation order candide <c.candide@laposte.net> - 2015-07-09 17:10 -0700
    Re: Evaluation order Terry Reedy <tjreedy@udel.edu> - 2015-07-09 21:45 -0400
    Re: Evaluation order Chris Angelico <rosuav@gmail.com> - 2015-07-10 12:02 +1000
      Re: Evaluation order candide <c.candide@laposte.net> - 2015-07-10 05:04 -0700
        Re: Evaluation order Ned Batchelder <ned@nedbatchelder.com> - 2015-07-10 05:19 -0700
        Re: Evaluation order Terry Reedy <tjreedy@udel.edu> - 2015-07-10 08:27 -0400
        Re: Evaluation order Chris Angelico <rosuav@gmail.com> - 2015-07-11 00:27 +1000
        Re: Evaluation order Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-07-10 15:49 +0100

#93618 — Evaluation order

Fromcandide <c.candide@laposte.net>
Date2015-07-09 17:10 -0700
SubjectEvaluation order
Message-ID<436cb6ac-59a4-44f1-be60-cdec1e509296@googlegroups.com>
The official doc explains that :

Python evaluates expressions from left to right.

cf. https://docs.python.org/3.3/reference/expressions.html#evaluation-order


But consider the following snippet :


>>> t=[2020, 42, 2015]
>>> t*(1+int(bool(t.sort())))
[42, 2015, 2020]
>>>


Is there not some contradiction with left-right evalutation? 




[toc] | [next] | [standalone]


#93620

FromTerry Reedy <tjreedy@udel.edu>
Date2015-07-09 21:45 -0400
Message-ID<mailman.378.1436492779.3674.python-list@python.org>
In reply to#93618
On 7/9/2015 8:10 PM, candide wrote:
> The official doc explains that :
> Python evaluates expressions from left to right.
> cf. https://docs.python.org/3.3/reference/expressions.html#evaluation-order


> But consider the following snippet :
>
>>>> t=[2020, 42, 2015]
>>>> t*(1+int(bool(t.sort())))
> [42, 2015, 2020]

> Is there not some contradiction with left-right evalutation?

No, as shown by the disassembled byte code
 >>> dis.dis("t*(1+int(bool(t.sort())))")
   1           0 LOAD_NAME            0 (t)
               3 LOAD_CONST           0 (1)
               6 LOAD_NAME            1 (int)
               9 LOAD_NAME            2 (bool)
              12 LOAD_NAME            0 (t)
              15 LOAD_ATTR            3 (sort)
              18 CALL_FUNCTION        0 (0 positional, 0 keyword pair)
              21 CALL_FUNCTION        1 (1 positional, 0 keyword pair)
              24 CALL_FUNCTION        1 (1 positional, 0 keyword pair)
              27 BINARY_ADD
              28 BINARY_MULTIPLY
              29 RETURN_VALUE

t.sort() sorts in place and returns None

-- 
Terry Jan Reedy

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


#93621

FromChris Angelico <rosuav@gmail.com>
Date2015-07-10 12:02 +1000
Message-ID<mailman.379.1436493764.3674.python-list@python.org>
In reply to#93618
On Fri, Jul 10, 2015 at 10:10 AM, candide <c.candide@laposte.net> wrote:
> The official doc explains that :
>
> Python evaluates expressions from left to right.
>
> cf. https://docs.python.org/3.3/reference/expressions.html#evaluation-order
>
>
> But consider the following snippet :
>
>
>>>> t=[2020, 42, 2015]
>>>> t*(1+int(bool(t.sort())))
> [42, 2015, 2020]
>>>>
>
>
> Is there not some contradiction with left-right evalutation?

I'm not sure what contradiction you're referring to, here. The
evaluation that you're pointing out says, as Terry showed via the
disassembly, that Python's first action is to look up the name 't' and
grab a reference to whatever object it points to. The execution of
t.sort() has to happen before the multiplication, because of the
parentheses.

ChrisA

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


#93631

Fromcandide <c.candide@laposte.net>
Date2015-07-10 05:04 -0700
Message-ID<ea920a46-804f-45dd-9c6b-1fb4c278be49@googlegroups.com>
In reply to#93621
Le vendredi 10 juillet 2015 04:02:56 UTC+2, Chris Angelico a écrit :


 
> I'm not sure what contradiction you're referring to, here. The
> evaluation that you're pointing out says, as Terry showed via the
> disassembly, that Python's first action is to look up the name 't' and
> grab a reference to whatever object it points to. 


But in order to perform an operation, the interpreter has to evaluate the operands and "evaluating" is not "grabbing a reference to". 

> The execution of
> t.sort() has to happen before the multiplication, because of the
> parentheses.
>



Official docs explains what evaluation is :

When the name is bound to an object, evaluation of the atom yields that object.

So, since the Python interpreter is performing evaluation from left to right, the first operand of the expression :

t*(1+int(bool(t.sort())))

evaluates to [2020, 42, 2015]. Next, the second operatand evaluates to the integer 1. So I was expecting the result to be a shallow copy of the first list [2020, 42, 2015] (the value of t before side effect produced by the sort method). On the contrary, the final result takes into in account the side effect and it is as if the first operand has been evaluated twice before execution of the multiplication operation.



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


#93633

FromNed Batchelder <ned@nedbatchelder.com>
Date2015-07-10 05:19 -0700
Message-ID<724768da-9b5e-4085-b999-ca2435a2e06f@googlegroups.com>
In reply to#93631
On Friday, July 10, 2015 at 8:04:36 AM UTC-4, candide wrote:
> Le vendredi 10 juillet 2015 04:02:56 UTC+2, Chris Angelico a écrit :
> 
> 
>  
> > I'm not sure what contradiction you're referring to, here. The
> > evaluation that you're pointing out says, as Terry showed via the
> > disassembly, that Python's first action is to look up the name 't' and
> > grab a reference to whatever object it points to. 
> 
> 
> But in order to perform an operation, the interpreter has to evaluate the operands and "evaluating" is not "grabbing a reference to". 
> 
> > The execution of
> > t.sort() has to happen before the multiplication, because of the
> > parentheses.
> >
> 
> 
> 
> Official docs explains what evaluation is :
> 
> When the name is bound to an object, evaluation of the atom yields that object.
> 
> So, since the Python interpreter is performing evaluation from left to right, the first operand of the expression :
> 
> t*(1+int(bool(t.sort())))
> 
> evaluates to [2020, 42, 2015]. Next, the second operatand evaluates to the integer 1. So I was expecting the result to be a shallow copy of the first list [2020, 42, 2015] (the value of t before side effect produced by the sort method). On the contrary, the final result takes into in account the side effect and it is as if the first operand has been evaluated twice before execution of the multiplication operation.

The first operand is t. Evaluating t does not make a copy of t, it is simply
a reference to t.  If t is later modified (by the sort method), the modified
data will be seen when t is used in the multiplication.

Python never implicitly copies lists (or any other data structure).  This
explains more about the mechanics of names and values: http://bit.ly/pynames1

--Ned.

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


#93634

FromTerry Reedy <tjreedy@udel.edu>
Date2015-07-10 08:27 -0400
Message-ID<mailman.391.1436531282.3674.python-list@python.org>
In reply to#93631
On 7/10/2015 8:04 AM, candide wrote:
> Le vendredi 10 juillet 2015 04:02:56 UTC+2, Chris Angelico a écrit :
>> I'm not sure what contradiction you're referring to, here. The
>> evaluation that you're pointing out says, as Terry showed via the
>> disassembly, that Python's first action is to look up the name 't' and
>> grab a reference to whatever object it points to.
>
> But in order to perform an operation, the interpreter has to evaluate
 > the operands and "evaluating" is not "grabbing a reference to".

In the CPython, evaluating a name is implemented as getting the 
reference corresponding to the name.

>> The execution of
>> t.sort() has to happen before the multiplication, because of the
>> parentheses.

> Official docs explains what evaluation is :
>
> When the name is bound to an object, evaluation of the atom yields that object.

Conceptually, that is exactly right.  How that is implemented on a 
computer in CPython is to load the address on the top of the virtual 
machine stack.

> So, since the Python interpreter is performing evaluation from left to right,
 > the first operand of the expression :
>
> t*(1+int(bool(t.sort())))
>
> evaluates to [2020, 42, 2015].

't' evaluates to the ***mutable*** list that 't' is bound to.

>  Next, the second operatand evaluates to the integer 1.

And in the process of that evaluation, the list is sorted.


-- 
Terry Jan Reedy

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


#93639

FromChris Angelico <rosuav@gmail.com>
Date2015-07-11 00:27 +1000
Message-ID<mailman.396.1436538455.3674.python-list@python.org>
In reply to#93631
On Fri, Jul 10, 2015 at 10:04 PM, candide <c.candide@laposte.net> wrote:
> But in order to perform an operation, the interpreter has to evaluate the operands and "evaluating" is not "grabbing a reference to".

Actually, it is. Suppose that instead of 't', you had a function call:

def get_t(announce, returnme=[]):
    print(announce)
    return returnme

get_t("setup").extend((2020, 42, 2015))
get_t("first")*(1+int(bool(get_t("second").sort())))

I think it's obvious from running the above code that get_t("first")
is evaluated before get_t("second") is. In the trivial case where the
operand is a simple name, yes, evaluating that name is simply "grab a
reference to the object this name references" (and in the case of
CPython, shove it onto the stack; other Pythons may operate some other
way).

> Official docs explains what evaluation is :
>
> When the name is bound to an object, evaluation of the atom yields that object.
>
> So, since the Python interpreter is performing evaluation from left to right, the first operand of the expression :
>
> t*(1+int(bool(t.sort())))
>
> evaluates to [2020, 42, 2015]. Next, the second operatand evaluates to the integer 1. So I was expecting the result to be a shallow copy of the first list [2020, 42, 2015] (the value of t before side effect produced by the sort method). On the contrary, the final result takes into in account the side effect and it is as if the first operand has been evaluated twice before execution of the multiplication operation.
>

The shallow copy isn't made until the multiplication is performed;
it's only at that point that a function takes two parameters and does
the work, something like this:

class list:
    def __mul__(self, count):
        result = []
        for i in range(count): result.extend(self)
        return result

Obviously you can't call that function until you know both the list
object and the count, so no copies are made until both those values
can be provided. The first operand evaluates to *the list with the
identity X*, the second operand evaluates to *the integer 1*, and then
the multiplication is performed.

Does that answer the question?

ChrisA

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


#93644

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2015-07-10 15:49 +0100
Message-ID<mailman.400.1436539805.3674.python-list@python.org>
In reply to#93631
On 10/07/2015 15:30, Thierry Chappuis wrote:

[snipped]

Please don't top post here as it can get irritating, especially in long 
threads, thanks.

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [standalone]


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


csiph-web