Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #88821 > unrolled thread
| Started by | jonas.thornvall@gmail.com |
|---|---|
| First post | 2015-04-11 08:00 -0700 |
| Last post | 2015-04-11 08:36 -0700 |
| Articles | 12 — 5 participants |
Back to article view | Back to comp.lang.python
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
| From | jonas.thornvall@gmail.com |
|---|---|
| Date | 2015-04-11 08:00 -0700 |
| Subject | Generarl 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]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-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]
| From | jonas.thornvall@gmail.com |
|---|---|
| Date | 2015-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]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-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]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2015-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-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]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2015-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2015-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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2015-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]
| From | jonas.thornvall@gmail.com |
|---|---|
| Date | 2015-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