From: Alister Ware on
On Sun, 11 Jul 2010 18:17:49 +0000, Duncan Booth wrote:

> wheres pythonmonks <wherespythonmonks(a)gmail.com> wrote:
>
>> I'm an old Perl-hacker, and am trying to Dive in Python. I have some
>> easy issues (Python 2.6)
>> which probably can be answered in two seconds:

without going into details on how to do these things in python(many
suggestions have already been made) i think you need to take a step back

Why do you want to do these particular things in this way?

is it because this is what is needed to get the job done or is it because
this is what's needed to get the job done in perl?

if the later then step back and think what is the real goal & program
accordingly.

Each language does things differently ( if they didn't we wouldn't have
different languages!)

what is Best for perl (or c , java, pascal or malbolge) may not
necessarily be the best for Python & vice Versa.


--
backups: always in season, never out of style.
From: Terry Reedy on
On 7/12/2010 4:48 AM, bart.c wrote:

>> >>> def foo():
>> print("Before:", locals())
>> x = 0
>> print("After:", locals())
>>
>>
>> >>> foo()
>> Before: {}
>> After: {'x': 0}
>
> That's interesting. So in Python, you can't tell what local variables a
> function has just by looking at it's code:

You are being fooled by the multiple meanings of the overloaded term
'variable'. Thing are clearer with the two terms 'name' and 'namespace'
(a set of name-object bindings).

Before compiling function code, an interpreter must read it and make a
classified list of *names*. The interpreter has to know the fixed set of
local names in order to know what to do with assignment statements. If
the interpreter can tell how many local names there are, so can you.

Before a function begins execution, all parameter names must be bound,
with no arguments left over. At that point, the local namespace consists
of those parameter-object bindings. During the execution of the
function, bindings may be added and deleted. The size of the local
namespace varies.

> def foo(day):
> if day=="Tuesday":
> x=0
> print ("Locals:",locals())
>
> #foo("Monday")
>
> Does foo() have 1 or 2 locals?

foo has 2 local names. Its local namespace starts with 1 binding and may
get another, depending of the value of the first.

If the size of the local namespace at some point of execution depends on
unknown information, then of course the size at that point is also unknown.

Here is another example:

>>> def f(a):
print(locals())
del a
print(locals())
a = None
print(locals())

>>> f(2)
{'a': 2}
{}
{'a': None}

--
Terry Jan Reedy

From: Alf P. Steinbach /Usenet on
* Rhodri James, on 12.07.2010 22:19:
> On Mon, 12 Jul 2010 13:56:38 +0100, bart.c <bartc(a)freeuk.com> wrote:
>
>> "Steven D'Aprano" <steve(a)REMOVE-THIS-cybersource.com.au> wrote in
>> message news:4c3aedd5$0$28647$c3e8da3(a)news.astraweb.com...
>>> On Mon, 12 Jul 2010 09:48:04 +0100, bart.c wrote:
>>>
>>>> That's interesting. So in Python, you can't tell what local variables a
>>>> function has just by looking at it's code:
>>
>>>> def foo(day):
>>>> if day=="Tuesday":
>>>> x=0
>>>> print ("Locals:",locals())
>>>>
>>>> #foo("Monday")
>>>>
>>>> Does foo() have 1 or 2 locals?
>>>
>>> That's easy for CPython: it prepares two slots for variables, but only
>>> creates one:
>>>
>>>>>> foo("Monday")
>>> ('Locals:', {'day': 'Monday'})
>>>>>> foo.func_code.co_varnames
>>> ('day', 'x')
>>>>>> foo.func_code.co_nlocals
>>> 2
>>>
>>> So, the question is, is x a local variable or not? It's not in locals,
>>> but the function clearly knows that it could be.
>>
>> So Alf P.S. could be right; x exists, but Python pretends it doesn't
>> until it's assigned to.
>
> CPython, not Python. And as Steven said, x *doesn't* exist. Allowance is
> made by that specific implementation of the interpreter because x
> *might* exist, but in this particular case it doesn't and a more dynamic
> implementation might choose not to reserve a slot just in case. x is
> created until it's actually used.

You are conflating existence with space allocation.

It's up to the implementation whether to allocate memory for the variable's
reference in any particular case where that memory isn't strictly required. This
is known as "optimization". Optimization depends on the implementation.

Existence of a variable means, among other things, that

* You can use the value, with guaranteed effect (either unassigned exception
or you get a proper value): in particular, you won't be accessing a global
if you're using the name of a local declared by a later assignment.

* You can assign to it.

How the Python implementation implements that is an implementation detail.

In short, how CPython does things is completely irrelevant to the language's
semantics, so you're conflating things here.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
From: Rami Chowdhury on
Perhaps I'm misunderstanding, but ...

On Jul 12, 2010, at 13:57 , Alf P. Steinbach /Usenet wrote:
>
> Existence of a variable means, among other things, that
>
> * You can use the value, with guaranteed effect (either unassigned exception
> or you get a proper value)

Surely by that definition any variable in any Python program "exists" -- you are guaranteed to get one of NameError, UnboundLocalError, or a value. That seems to argue away the meaning of the word entirely, and renders it not particularly useful.

>
> How the Python implementation implements that is an implementation detail.
>
> In short, how CPython does things is completely irrelevant to the language's semantics, so you're conflating things here.
>

As I'd understood the previous discussion, it is the CPython implementation that reserves local names and produces UnboundLocalErrors. The language semantics don't call for it, and another implementation might choose to handle function locals the same way as globals, through a namespace dictionary -- in which case the variable *wouldn't* exist in any way, shape, or form until it was assigned to.

What am I getting wrong here?

-------------
Rami Chowdhury
"Never assume malice when stupidity will suffice." -- Hanlon's Razor
408-597-7068 (US) / 07875-841-046 (UK) / 0189-245544 (BD)


From: Alf P. Steinbach /Usenet on
* Rami Chowdhury, on 13.07.2010 00:14:
> Perhaps I'm misunderstanding, but ...
>
> On Jul 12, 2010, at 13:57 , Alf P. Steinbach /Usenet wrote:
>>
>> Existence of a variable means, among other things, that
>>
>> * You can use the value, with guaranteed effect (either unassigned exception
>> or you get a proper value)
>
> Surely by that definition any variable in any Python program "exists" -- you
> are guaranteed to get one of NameError, UnboundLocalError, or a value. That
> seems to argue away the meaning of the word entirely, and renders it not
> particularly useful.

No, you're conflating non-existence (NameError) with accessing the value of an
existing but unassigned variable (UnboundLocalError). It is like arguing that
vacuum is the same as cement because sticking your head into it for ten minutes
or so yields an effect -- you're dead -- that in many ways is just about the
same. However, the tangible existence of cement means that one can pour it over
your head, /adding/ the cement, while it's difficult to pour vacuum over your
head; rather, for the latter effect one would need to /remove/ the air around
your head. OK, the analogy halts a little. But I think you'll get it.

Similarly, you can add a variable and thereby cause am UnboundLocalError, and
you can remove a variable and thereby cause a NameError.


>> How the Python implementation implements that is an implementation detail.
>>
>> In short, how CPython does things is completely irrelevant to the language's
> semantics, so you're conflating things here.
>>
>
> As I'd understood the previous discussion, it is the CPython implementation
> that reserves local names and produces UnboundLocalErrors. The language
> semantics don't call for it, and another implementation might choose to handle
> function locals the same way as globals, through a namespace dictionary -- in
> which case the variable *wouldn't* exist in any way, shape, or form until it
> was assigned to.
>
> What am I getting wrong here?

The bit about the language semantics not specifying the effect.

From the 3.1.1 language reference �4.1:

"When a name is not found at all, a NameError exception is raised. If the name
refers to a local variable that has not been bound, a UnboundLocalError
exception is raised. UnboundLocalError is a subclass of NameError."

And it goes on to elaborate on that, a little later:

"If a name binding operation occurs anywhere within a code block, all uses of
the name within the block are treated as references to the current block. This
can lead to errors when a name is used within a block before it is bound. This
rule is subtle. Python lacks declarations and allows name binding operations to
occur anywhere within a code block. The local variables of a code block can be
determined by scanning the entire text of the block for name binding operations."

In short, Stephen D'Aprano's remarks were technically on the spot, while Rhodri
James's follow up, that it seems influenced your response, was meaningless
mumbo-jumbo with strong emphasis added repeatedly to denials of reality.

This is the usual reaction of the religious when exposed to reality.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>