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


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

Generarl programming question.

Started byjonas.thornvall@gmail.com
First post2015-04-11 08:00 -0700
Last post2015-04-11 08:36 -0700
Articles 12 — 5 participants

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


Contents

  Generarl programming question. jonas.thornvall@gmail.com - 2015-04-11 08:00 -0700
    Re: Generarl programming question. Chris Angelico <rosuav@gmail.com> - 2015-04-12 01:15 +1000
      Re: Generarl programming question. jonas.thornvall@gmail.com - 2015-04-11 08:22 -0700
        Re: Generarl programming question. Chris Angelico <rosuav@gmail.com> - 2015-04-12 01:28 +1000
      Re: Generarl programming question. Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-04-11 18:23 +0200
        Re: Generarl programming question. Terry Reedy <tjreedy@udel.edu> - 2015-04-11 14:47 -0400
          Re: Generarl programming question. Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-04-11 21:19 +0200
            Re: Generarl programming question. Terry Reedy <tjreedy@udel.edu> - 2015-04-11 17:12 -0400
              Re: Generarl programming question. Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-04-12 00:05 +0200
                Re: Generarl programming question. Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-04-12 15:04 +1000
    Re: Generarl programming question. Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-04-12 01:25 +1000
      Re: Generarl programming question. jonas.thornvall@gmail.com - 2015-04-11 08:36 -0700

#88821 — Generarl programming question.

Fromjonas.thornvall@gmail.com
Date2015-04-11 08:00 -0700
SubjectGenerarl programming question.
Message-ID<dcb7fd6b-3a96-47e8-91f6-49b21f7bf605@googlegroups.com>
If two functions crossreference eachother back and forth what happen with the local variables.

Will there be a new instance of function holding the variables or do they get messed up?

[toc] | [next] | [standalone]


#88822

FromChris Angelico <rosuav@gmail.com>
Date2015-04-12 01:15 +1000
Message-ID<mailman.222.1428765309.12925.python-list@python.org>
In reply to#88821
On Sun, Apr 12, 2015 at 1:00 AM,  <jonas.thornvall@gmail.com> wrote:
> If two functions crossreference eachother back and forth what happen with the local variables.
>
> Will there be a new instance of function holding the variables or do they get messed up?

You mean if one function calls another, and that function calls the
first? That's called "mutual recursion":

def func1(x):
    if x % 2: return x + 1
    return func2(x - 2)

def func2(x):
    if x % 3: return x + 2
    return func1(x - 3)

The 'x' inside each function is completely separate, no matter how
many times they get called. They're usually stored on something called
a "call stack" - you put another sheet of paper on top of the stack
every time you call a function, local variables are all written on
that paper, and when you return from a function, you discard the top
sheet and see what's underneath.

For more information, search the web for the key terms in the above
description, particularly the ones I put in quotes.

If this isn't what you're talking about, the best way to clarify your
question is probably to post a simple (even stupidly trivial, like the
one above) example, and ask a question about that code. Someone'll
doubtless help out!

ChrisA

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


#88823

Fromjonas.thornvall@gmail.com
Date2015-04-11 08:22 -0700
Message-ID<1f4ab217-ed8e-4d8c-ba61-907465a4839a@googlegroups.com>
In reply to#88822
Den lördag 11 april 2015 kl. 17:16:09 UTC+2 skrev Chris Angelico:
> On Sun, Apr 12, 2015 at 1:00 AM,  <jonas.thornvall@gmail.com> wrote:
> > If two functions crossreference eachother back and forth what happen with the local variables.
> >
> > Will there be a new instance of function holding the variables or do they get messed up?
> 
> You mean if one function calls another, and that function calls the
> first? That's called "mutual recursion":
> 
> def func1(x):
>     if x % 2: return x + 1
>     return func2(x - 2)
> 
> def func2(x):
>     if x % 3: return x + 2
>     return func1(x - 3)
> 
> The 'x' inside each function is completely separate, no matter how
> many times they get called. They're usually stored on something called
> a "call stack" - you put another sheet of paper on top of the stack
> every time you call a function, local variables are all written on
> that paper, and when you return from a function, you discard the top
> sheet and see what's underneath.
> 
> For more information, search the web for the key terms in the above
> description, particularly the ones I put in quotes.
> 
> If this isn't what you're talking about, the best way to clarify your
> question is probably to post a simple (even stupidly trivial, like the
> one above) example, and ask a question about that code. Someone'll
> doubtless help out!
> 
> ChrisA

Thanks i was worried, i try to make a generic base choice algorithm that should work for anybase, and i just realised that the bignumb add would need to call the bignumb subtraction and viceversa. I thought there may be instances but i was not sure. 

But I have a feeling the code will be hard to debug.

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


#88825

FromChris Angelico <rosuav@gmail.com>
Date2015-04-12 01:28 +1000
Message-ID<mailman.223.1428766115.12925.python-list@python.org>
In reply to#88823
On Sun, Apr 12, 2015 at 1:22 AM,  <jonas.thornvall@gmail.com> wrote:
> Thanks i was worried, i try to make a generic base choice algorithm that should work for anybase, and i just realised that the bignumb add would need to call the bignumb subtraction and viceversa. I thought there may be instances but i was not sure.
>
> But I have a feeling the code will be hard to debug.

The thing to watch out for is unbounded recursion, where they might
call each other forever. But you could easily define your two
functions to fall back to the other like this:

def add(x, y):
    if is_negative(y): return subtract(x, -y)
    # implement addition with known-positive y

def subtract(x, y):
    if is_negative(y): return add(x, -y)
    # implement subtraction with known-positive y

There's no problem here, and no possible conflict. (I don't know how
it'd actually help, implementing it like this, but it's certainly
legal.)

ChrisA

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


#88827

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-04-11 18:23 +0200
Message-ID<12030326.cc9aoE7jz1@PointedEars.de>
In reply to#88822
Chris Angelico wrote:

> The 'x' inside each function is completely separate, no matter how
> many times they get called. They're usually stored on something called
> a "call stack" - you put another sheet of paper on top of the stack
> every time you call a function, local variables are all written on
> that paper, and when you return from a function, you discard the top
> sheet and see what's underneath.

Thank you for that description; I shall use it from now on when teaching 
laymen about the call stack.

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

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


#88836

FromTerry Reedy <tjreedy@udel.edu>
Date2015-04-11 14:47 -0400
Message-ID<mailman.227.1428778121.12925.python-list@python.org>
In reply to#88827
On 4/11/2015 12:23 PM, Thomas 'PointedEars' Lahn wrote:
> Chris Angelico wrote:
>
>> The 'x' inside each function is completely separate, no matter how
>> many times they get called. They're usually stored on something called
>> a "call stack" - you put another sheet of paper on top of the stack
>> every time you call a function, local variables are all written on
>> that paper, and when you return from a function, you discard the top
>> sheet and see what's underneath.
>
> Thank you for that description; I shall use it from now on when teaching
> laymen about the call stack.

What Chris is describing is one local namespace (sheet of paper) per 
function *call*.  In early Fortran (at least the first version I used), 
there was one local namespace (sheet) per *function*.  The call stack 
was a stack of (pointers to) functions.  While a function object was in 
use (after a call, before the return), it could not be called again.  In 
other words, recursion, direct or indirect, was not allowed.  I believe 
the same was (is?) true of some versions of BASIC.

It has been proposed that Python use a hybrid model.  Function objects 
would have space for local variables for the first call, but there would 
also be a mechanism to allocate additional 'sheets' for recursive calls. 
  The idea is that most functions are not called recursively, so the 
overhead of allocating and freeing the per-call space is usually not 
needed.  I do not believe that anyone has implemented the idea to test 
feasibility and the actual speedup in relation to the additional complexity.

-- 
Terry Jan Reedy

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


#88838

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-04-11 21:19 +0200
Message-ID<3458425.12qjem4LOE@PointedEars.de>
In reply to#88836
Terry Reedy wrote:

> On 4/11/2015 12:23 PM, Thomas 'PointedEars' Lahn wrote:
>> Chris Angelico wrote:
>>> The 'x' inside each function is completely separate, no matter how
>>> many times they get called. They're usually stored on something called
>>> a "call stack" - you put another sheet of paper on top of the stack
>>> every time you call a function, local variables are all written on
>>> that paper, and when you return from a function, you discard the top
>>> sheet and see what's underneath.
>>
>> Thank you for that description; I shall use it from now on when teaching
>> laymen about the call stack.
> 
> What Chris is describing is one local namespace (sheet of paper) per
> function *call*.

I *know* what he is describing: the *call* stack.

> In early Fortran (at least the first version I used),
> there was one local namespace (sheet) per *function*.

The names in such namespaces are now called static variables.  AFAIK, Python 
does not have them, but PHP, for example, has:

  function foo ()
  {
    static $bar = 1;
    $bar *= 2;
    return $bar;
  }

The variable $bar then keeps its last value for subsequent calls of foo().

> The call stack was a stack of (pointers to) functions.

It would appear that the commonly used definition of “call stack” has 
considerably changed since then, since I have been programming computers for 
more than two decades now (not including FORTRAN, though) and never heard of
your definition before.

> It has been proposed that Python use a hybrid model.  Function objects 

Interesting.  I did not know that functions are objects in Python, too.

> would have space for local variables for the first call, but there would 
> also be a mechanism to allocate additional 'sheets' for recursive calls. 
>   The idea is that most functions are not called recursively, so the 
> overhead of allocating and freeing the per-call space is usually not 
> needed.  I do not believe that anyone has implemented the idea to test 
> feasibility and the actual speedup in relation to the additional 
> complexity.

ISTM that such static variables are the remains of non-object-oriented 
programming.  In a language where functions are first-class objects, you 
would use a closure instead.  And in OOP you would solve the problem with an 
object holding the value in a property that survives exiting the execution 
context of the function/method.  It is not a good idea to reintroduce 
obsolete concepts into Python.
 
-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

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


#88842

FromTerry Reedy <tjreedy@udel.edu>
Date2015-04-11 17:12 -0400
Message-ID<mailman.233.1428786783.12925.python-list@python.org>
In reply to#88838
On 4/11/2015 3:19 PM, Thomas 'PointedEars' Lahn wrote:
> Terry Reedy wrote:
>
>> On 4/11/2015 12:23 PM, Thomas 'PointedEars' Lahn wrote:
>>> Chris Angelico wrote:
>>>> The 'x' inside each function is completely separate, no matter how
>>>> many times they get called. They're usually stored on something called
>>>> a "call stack" - you put another sheet of paper on top of the stack
>>>> every time you call a function, local variables are all written on
>>>> that paper, and when you return from a function, you discard the top
>>>> sheet and see what's underneath.
>>>
>>> Thank you for that description; I shall use it from now on when teaching
>>> laymen about the call stack.
>>
>> What Chris is describing is one local namespace (sheet of paper) per
>> function *call*.

> I *know* what he is describing: the *call* stack.

My comment above was directed not at you specifically but at the OP, 
Jonas, who appears to have had a mental model (like the following) in 
which recursion is not possible.  I think this mental model is fairly 
common among programming newbies.  And it is not crazy, just obsolete 
and superceded.  And, we constantly talk about a function's local names, 
which is correct, without constantly adding the caveat that in Python 
(and most modern languages) they are instanced per call.

I think of functions as being something like a class, in that each call 
gives a new instance with a new set of named values.

>> In early Fortran (at least the first version I used),
>> there was one local namespace (sheet) per *function*.
>
> The names in such namespaces are now called static variables.  AFAIK, Python
> does not have them, but PHP, for example, has:
>
>    function foo ()
>    {
>      static $bar = 1;
>      $bar *= 2;
>      return $bar;
>    }
>
> The variable $bar then keeps its last value for subsequent calls of foo().

In Python, one can do something similar with attributes, except that 
attributes are easily accessible from outside the function.  Mutable 
defaults probably come closer.

def doubler(_val=[1])"
   _val[0] *= 2
   return _val[0]

print(doubler(), doubler(), doubler())
# 2 4 8

>> The call stack was a stack of (pointers to) functions.
>
> It would appear that the commonly used definition of “call stack” has
> considerably changed since then, since I have been programming computers for
> more than two decades now (not including FORTRAN, though) and never heard of
> your definition before.

I don't know what the stack required for returns was called in Fortran 
or how it was implemented in any particular compiler.

>> It has been proposed that Python use a hybrid model.  Function objects
>
> Interesting.  I did not know that functions are objects in Python, too.

In Python, everything you can bind a name to is an object, and in 3.x, 
an instance of the base class 'object'.

-- 
Terry Jan Reedy

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


#88845

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-04-12 00:05 +0200
Message-ID<4867215.Po4C3FaEzt@PointedEars.de>
In reply to#88842
Terry Reedy wrote:

> On 4/11/2015 3:19 PM, Thomas 'PointedEars' Lahn wrote:
>> Terry Reedy wrote:
>>> What Chris is describing is one local namespace (sheet of paper) per
>>> function *call*.
>> I *know* what he is describing: the *call* stack.
> 
> My comment above was directed not at you specifically but at the OP,
> Jonas, […]

ACK

>> The variable $bar then keeps its last value for subsequent calls of
>> foo().
> 
> In Python, one can do something similar with attributes, except that
> attributes are easily accessible from outside the function.

AISB.  Python’s “attributes” are named “properties” elsewhere.

> Mutable defaults probably come closer.
> 
> def doubler(_val=[1])"
>    _val[0] *= 2
>    return _val[0]
> 
> print(doubler(), doubler(), doubler())
> # 2 4 8

Fascinating.  Thanks.

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

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


#88857

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-04-12 15:04 +1000
Message-ID<5529fcf7$0$12996$c3e8da3$5496439d@news.astraweb.com>
In reply to#88845
Thomas, before I reply to your comment, I have a meta-comment to make.

Your signature says "Please do not cc me. / Bitte keine Kopien per E-Mail."
which suggests that you do not want to be emailed. But your post included
an explicit "Mail-Copies-To: usenet@PointedEars.de" header which compliant
news readers should interpret as "reply by email as well as news".

So which is lying? Your sig, that says not to email you, or the
Mail-Copies-To header, which says to email you?

Back to Python...


On Sun, 12 Apr 2015 08:05 am, Thomas 'PointedEars' Lahn wrote:

>> In Python, one can do something similar with attributes, except that
>> attributes are easily accessible from outside the function.
> 
> AISB.  Python’s “attributes” are named “properties” elsewhere.

Other common names include “members” (mostly in C++ I believe)
and “variables” (mostly Java, I believe). I think using “variable” to
describe an attribute/property/member of an object is a terrible idea.



-- 
Steven

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


#88824

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-04-12 01:25 +1000
Message-ID<55293cff$0$12979$c3e8da3$5496439d@news.astraweb.com>
In reply to#88821
On Sun, 12 Apr 2015 01:00 am, jonas.thornvall@gmail.com wrote:

> If two functions crossreference eachother back and forth what happen with
> the local variables.

Nothing. They are local to the function that creates them.


> Will there be a new instance of function holding the variables or do they
> get messed up?

No to both of those. You have two functions, each with it's own locals.


def spam():
    colour = "red"
    print("Inside spam: colour is:", colour)
    eggs()
    print("Inside spam after calling eggs: colour is:", colour)
    eggs()


def eggs():
    colour = "yellow"
    print("Inside eggs: colour is:", colour)


Calling spam() gives you this output:

py> spam()
Inside spam: colour is: red
Inside eggs: colour is: yellow
Inside spam after calling eggs: colour is: red
Inside eggs: colour is: yellow


Even if the functions call each other (mutual recursion) each function's
local variables remain local.



-- 
Steven

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


#88826

Fromjonas.thornvall@gmail.com
Date2015-04-11 08:36 -0700
Message-ID<ce9408cd-4622-4c1b-a515-45df7dace0bc@googlegroups.com>
In reply to#88824
Den lördag 11 april 2015 kl. 17:26:03 UTC+2 skrev Steven D'Aprano:
> On Sun, 12 Apr 2015 01:00 am, jonas.thornvall@gmail.com wrote:
> 
> > If two functions crossreference eachother back and forth what happen with
> > the local variables.
> 
> Nothing. They are local to the function that creates them.
> 
> 
> > Will there be a new instance of function holding the variables or do they
> > get messed up?
> 
> No to both of those. You have two functions, each with it's own locals.
> 
> 
> def spam():
>     colour = "red"
>     print("Inside spam: colour is:", colour)
>     eggs()
>     print("Inside spam after calling eggs: colour is:", colour)
>     eggs()
> 
> 
> def eggs():
>     colour = "yellow"
>     print("Inside eggs: colour is:", colour)
> 
> 
> Calling spam() gives you this output:
> 
> py> spam()
> Inside spam: colour is: red
> Inside eggs: colour is: yellow
> Inside spam after calling eggs: colour is: red
> Inside eggs: colour is: yellow
> 
> 
> Even if the functions call each other (mutual recursion) each function's
> local variables remain local.
> 
> 
> 
> -- 
> Steven

I don't think it matter butt eggs also calls spam, once more.

[toc] | [prev] | [standalone]


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


csiph-web