Re: The meaning of = (Was: tough-to-explain Python)

2009-07-14 Thread Lawrence D'Oliveiro
In message pan.2009.07.14.03.45...@remove.this.cybersource.com.au, Steven 
D'Aprano wrote:

 Are we supposed to interpret that post as Dumb Insolence or just Dumb?

Insolence indeed ... another wanker to plonk, I think.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-13 Thread Lawrence D'Oliveiro
In message h3bogf$oo...@panix3.panix.com, Aahz wrote:

 In article h3bagu$52...@lust.ihug.co.nz,
 Lawrence D'Oliveiro  l...@geek-central.gen.new_zealand wrote:
In message h37gv5$r8...@panix3.panix.com, Aahz wrote:

 It helps to remember that names and namespaces are in many
 ways syntactic sugar for dicts or lists.

Interesting, though, that Python insists on maintaining a distinction
between c[x] and c.x, whereas JavaScript doesn't bother.
 
 Why do you say insists?
 
 class AttrDict:
 def __getitem__(self, key):
 return getattr(self, key)

OK, let's try it:

 c = {}
 c[x] = 3
 c.x = 4   
Traceback (most recent call last):
  File stdin, line 1, in module
AttributeError: 'dict' object has no attribute 'x'
 class AttrDict:
... def __getitem__(self, key):
... return getattr(self, key)
...
 c.x = 4
Traceback (most recent call last):
  File stdin, line 1, in module
AttributeError: 'dict' object has no attribute 'x'

Nope, still doesn't work...

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-11 Thread Lawrence D'Oliveiro
In message h37gv5$r8...@panix3.panix.com, Aahz wrote:

 It helps to remember that names and namespaces are in many
 ways syntactic sugar for dicts or lists.

Interesting, though, that Python insists on maintaining a distinction 
between c[x] and c.x, whereas JavaScript doesn't bother.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-11 Thread greg

Lawrence D'Oliveiro wrote:

Interesting, though, that Python insists on maintaining a distinction 
between c[x] and c.x, whereas JavaScript doesn't bother.


And that distinction is a good thing. It means, for
example, that dictionaries can have methods without
colliding with the key space of the items put into
them.

--
Greg
--
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-11 Thread Aahz
In article h3bagu$52...@lust.ihug.co.nz,
Lawrence D'Oliveiro  l...@geek-central.gen.new_zealand wrote:
In message h37gv5$r8...@panix3.panix.com, Aahz wrote:

 It helps to remember that names and namespaces are in many
 ways syntactic sugar for dicts or lists.

Interesting, though, that Python insists on maintaining a distinction 
between c[x] and c.x, whereas JavaScript doesn't bother.

Why do you say insists?

class AttrDict:
def __getitem__(self, key):
return getattr(self, key)
-- 
Aahz (a...@pythoncraft.com)   * http://www.pythoncraft.com/

as long as we like the same operating system, things are cool. --piranha
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-10 Thread Aahz
[excessive quoting ahead, I'm too tired to trim]

In article h32i2o$eo...@reader1.panix.com, kj  no.em...@please.post wrote:
In h32fon$26...@panix3.panix.com a...@pythoncraft.com (Aahz) writes:
In article h32eoh$ql...@reader1.panix.com, kj  no.em...@please.post wrote:

OK, so, scratching from my original post the case

identifier.identifier = expression

(as being a special case of identifier = expression), still,
to the extent that I understand your post, the = in

  x = 1

means something fundamentally different (in terms of Python's
underlying implementation) from the = in

  y[0] = 1

No?

No.  ;-)

No???  Just when I thought I finally understood all this!

What's different is not the ``=`` but the construction of the
assignment target before ``=`` gets executed.

Hmm.  OK, I went to the link you posted in your other message
(http://docs.python.org/reference/simple_stmts.html#assignment-statements)
and I find this (my emphasis):

Assignment of an object to a single target is recursively defined as 
 follows.

* If the target is an identifier (name):

 o If the name does not occur in a global statement in
   the current code block: the name is bound to the object
^
   in the current local namespace.

 o Otherwise: the name is bound to the object in the
   ^
   current global namespace.

  The name is rebound if it was already bound. This may cause
  the reference count for the object previously bound to the
  name to reach zero, causing the object to be deallocated and
  its destructor (if it has one) to be called.

* If the target is a target list enclosed in parentheses or in
  square brackets... (I'LL IGNORE THIS FOR NOW)

* If the target is an attribute reference: The primary expression
  in the reference is evaluated. It should yield an object with
  assignable attributes; if this is not the case, TypeError is
  raised. That object is then asked to assign the assigned
  
  object to the given attribute; if it cannot perform the
  ^^
  assignment, it raises an exception (usually but not necessarily
  AttributeError).

* If the target is a subscription: The primary expression in
  the reference is evaluated. It should yield either a mutable
  sequence object (such as a list) or a mapping object (such
  as a dictionary). Next, the subscript expression is evaluated.

  If the primary is a mutable sequence object (such as a
  list),...  [CONDITIONS ON THE INDEX EXPRESSION OMITTED]...
  the sequence is asked to assign the assigned object to its
  ^^^
  item with that index

  If the primary is a mapping object (such as a dictionary),...
  [CONDITIONS ON THE SUBSCRIPT EXPRESSION OMITTED]... the
  ^^^
  mapping is then asked to create a key/datum pair which maps
  ^^^
  the subscript to the assigned object.
  

* If the target is a slicing: [INDEX STUFF OMITTED]... the
   ^^^
  sequence object is asked to replace the slice with the items
  
  of the assigned sequence...
  

OK, I originally interpreted what Lundh wrote in his two articles
that the binding described at the very beginning (i.e. when the
target is an identifier), which I take to make an entry or modify
such an entry in a namespace, is a *categorically different*
operation from the remaining operations underlined above.

I interpreted Paul Boddie's correction in his response to me as
saying that the assignment mentioned for the case when the target
is an attribute reference is actually a special case of the
assignment to simple identifiers (i.e. it also means binding).

But that still leaves all the other assignments (or the like)
underlined above.  I don't think that the full definitions of these
remaining cases are covered by the same rule, even though the rule
is described as recursive.  I think that the writer has something
else in mind, and in particular, something *other* than binding,
but the author remains vague on exactly what this means.

Clearly, both Lundh and the documentation draw some distinction
between binding and some other forms of assignment (which remain
ill-defined throughout).  This distinction is what I was referring
to when I said that = means different things in different contexts.

Consider this:

x = 1
globals()['x'] = 1
locals()[1] = 1

What's the difference between the three?  Although there's a lot of
machinery amenable to manipulation, with the 

Re: The meaning of = (Was: tough-to-explain Python)

2009-07-09 Thread Lawrence D'Oliveiro
In message h3291j$mf...@reader1.panix.com, kj wrote:

 .., Lundh writes:
 
   Assignment statements modify namespaces, not objects.

counterexample

 a = [3]
 b = a

These may indeed modify a namespace, not any object. However:

 a[:] = [4]
 a
[4]
 b
[4]

What change has happened to the namespace in this case? None. Yet an object 
has changed.

/counterexample

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-08 Thread Paul Boddie
On 8 Jul, 16:04, kj no.em...@please.post wrote:

   identifier = expression

 and not to those like, for example,

   identifier[expression] = expression

 or

   identifier.identifier = expression

 The former are syntatic sugar for certain namespace modifications
 that leave objects unchanged.  The latter are syntactic sugar for
 certain object-modifying method calls that leave namespaces unchanged.

Almost. The latter can modify namespaces - the objects themselves -
but through properties or dynamic attribute access, they may choose
not to modify such a namespace. Really, we can phrase assignment (=)
as follows:

thing = expression # make thing refer to the result of
expression

Here, thing has to provide something that can be made to refer to
something else, such as a name within a namespace - the first and last
of your cases - or an item or slice within a sequence - the special
second case which is actually handled differently from the other
cases.

Meanwhile, the expression will always provide an object to refer to,
never anything of the nature of thing referring to something else.
In other words, if you have this...

x[1] = y[2]

...then the expression which is y[2] will yield an object which is
then assigned to x[1]. The concept of y[2] is not assignable - it must
be fully evaluated and produce the object at location #2 in the
sequence for assignment.

I suppose you could say that the left-hand side thing is like a sign
on a signpost which always points to a real place, not another sign on
a signpost. You could stretch this analogy by treating sequences as
signposts holding many signs, each adjustable to point to something
different. Since signposts (not the individual signs) are located in
real places, they would naturally be acceptable as targets of
assignments: where the signs are allowed to point to. Indeed, this
would be a world of signposts with the occasional primitive value
mixed in to keep weary travellers interested. ;-)

Paul
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-08 Thread kj
In 0778f257-d36c-4e13-93ea-bf8d448c8...@b15g2000yqd.googlegroups.com Paul 
Boddie p...@boddie.org.uk writes:

On 8 Jul, 16:04, kj no.em...@please.post wrote:

 =A0 identifier =3D expression

 and not to those like, for example,

 =A0 identifier[expression] =3D expression

 or

 =A0 identifier.identifier =3D expression

 The former are syntatic sugar for certain namespace modifications
 that leave objects unchanged. =A0The latter are syntactic sugar for
 certain object-modifying method calls that leave namespaces unchanged.

Almost. The latter can modify namespaces - the objects themselves -
but through properties or dynamic attribute access, they may choose
not to modify such a namespace. Really, we can phrase assignment (=3D)
as follows:

thing =3D expression # make thing refer to the result of
expression

Here, thing has to provide something that can be made to refer to
something else, such as a name within a namespace - the first and last
of your cases - or an item or slice within a sequence - the special
second case which is actually handled differently from the other
cases.

Thanks for this correction.

OK, so, scratching from my original post the case

identifier.identifier = expression

(as being a special case of identifier = expression), still,
to the extent that I understand your post, the = in

  x = 1

means something fundamentally different (in terms of Python's
underlying implementation) from the = in

  y[0] = 1

No?

You could stretch this analogy by treating sequences as
signposts holding many signs, each adjustable to point to something
different.

Notionally, yes, I can see that, but there's no counterpart of this
analogy at the level of Python's implementation.  The x above is
a sign, as you put it, i.e. an entry in a namespace, but y[0]
is, in essence, a method call.

kj
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-08 Thread Aahz
In article 0778f257-d36c-4e13-93ea-bf8d448c8...@b15g2000yqd.googlegroups.com,
Paul Boddie  p...@boddie.org.uk wrote:

Almost. The latter can modify namespaces - the objects themselves -
but through properties or dynamic attribute access, they may choose
not to modify such a namespace. Really, we can phrase assignment (=)
as follows:

thing = expression # make thing refer to the result of expression

Right, except s/thing/target/

http://docs.python.org/reference/simple_stmts.html#assignment-statements
-- 
Aahz (a...@pythoncraft.com)   * http://www.pythoncraft.com/

as long as we like the same operating system, things are cool. --piranha
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-08 Thread Aahz
In article h32eoh$ql...@reader1.panix.com, kj  no.em...@please.post wrote:

OK, so, scratching from my original post the case

identifier.identifier = expression

(as being a special case of identifier = expression), still,
to the extent that I understand your post, the = in

  x = 1

means something fundamentally different (in terms of Python's
underlying implementation) from the = in

  y[0] = 1

No?

No.  ;-)  What's different is not the ``=`` but the construction of the
assignment target before ``=`` gets executed.  Consider also this:

x, y = y, x
-- 
Aahz (a...@pythoncraft.com)   * http://www.pythoncraft.com/

as long as we like the same operating system, things are cool. --piranha
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-08 Thread kj
In h32fon$26...@panix3.panix.com a...@pythoncraft.com (Aahz) writes:

In article h32eoh$ql...@reader1.panix.com, kj  no.em...@please.post wrote:

OK, so, scratching from my original post the case

identifier.identifier = expression

(as being a special case of identifier = expression), still,
to the extent that I understand your post, the = in

  x = 1

means something fundamentally different (in terms of Python's
underlying implementation) from the = in

  y[0] = 1

No?

No.  ;-)

No???  Just when I thought I finally understood all this!

What's different is not the ``=`` but the construction of the
assignment target before ``=`` gets executed.

Hmm.  OK, I went to the link you posted in your other message
(http://docs.python.org/reference/simple_stmts.html#assignment-statements)
and I find this (my emphasis):

Assignment of an object to a single target is recursively defined as 
follows.

* If the target is an identifier (name):

  o If the name does not occur in a global statement in
the current code block: the name is bound to the object
^
in the current local namespace.

  o Otherwise: the name is bound to the object in the
   ^
current global namespace.

  The name is rebound if it was already bound. This may cause
  the reference count for the object previously bound to the
  name to reach zero, causing the object to be deallocated and
  its destructor (if it has one) to be called.

* If the target is a target list enclosed in parentheses or in
  square brackets... (I'LL IGNORE THIS FOR NOW)

* If the target is an attribute reference: The primary expression
  in the reference is evaluated. It should yield an object with
  assignable attributes; if this is not the case, TypeError is
  raised. That object is then asked to assign the assigned
  
  object to the given attribute; if it cannot perform the
  ^^
  assignment, it raises an exception (usually but not necessarily
  AttributeError).

* If the target is a subscription: The primary expression in
  the reference is evaluated. It should yield either a mutable
  sequence object (such as a list) or a mapping object (such
  as a dictionary). Next, the subscript expression is evaluated.

  If the primary is a mutable sequence object (such as a
  list),...  [CONDITIONS ON THE INDEX EXPRESSION OMITTED]...
  the sequence is asked to assign the assigned object to its
  ^^^
  item with that index

  If the primary is a mapping object (such as a dictionary),...
  [CONDITIONS ON THE SUBSCRIPT EXPRESSION OMITTED]... the
  ^^^
  mapping is then asked to create a key/datum pair which maps
  ^^^
  the subscript to the assigned object.
  

* If the target is a slicing: [INDEX STUFF OMITTED]... the
   ^^^
  sequence object is asked to replace the slice with the items
  
  of the assigned sequence...
  

OK, I originally interpreted what Lundh wrote in his two articles
that the binding described at the very beginning (i.e. when the
target is an identifier), which I take to make an entry or modify
such an entry in a namespace, is a *categorically different*
operation from the remaining operations underlined above.

I interpreted Paul Boddie's correction in his response to me as
saying that the assignment mentioned for the case when the target
is an attribute reference is actually a special case of the
assignment to simple identifiers (i.e. it also means binding).

But that still leaves all the other assignments (or the like)
underlined above.  I don't think that the full definitions of these
remaining cases are covered by the same rule, even though the rule
is described as recursive.  I think that the writer has something
else in mind, and in particular, something *other* than binding,
but the author remains vague on exactly what this means.

Clearly, both Lundh and the documentation draw some distinction
between binding and some other forms of assignment (which remain
ill-defined throughout).  This distinction is what I was referring
to when I said that = means different things in different contexts.

kj
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: The meaning of = (Was: tough-to-explain Python)

2009-07-08 Thread Terry Reedy

kj wrote:


To clarify, this comes from my reading of Fredrik Lundh's pages
Python Objects (http://effbot.org/zone/python-objects.htm) and
Call By Object (http://effbot.org/zone/call-by-object.htm).

[snip]

[END OF LENGTHY QUOTE]

Therefore, extending just a bit beyond Lundh's explanation, if we
did:

name = []
name.append(1)
name[0] = 3

...the second assignment would amount to a method call on the object
called 'name', an operation of a very different nature (according
to Lundh) from the first assignment, which is a modification of a
namespace.


I disagree. Assignment creates an association. Modification of a 
namespace, when implemented, amounts to a method call on the concrete 
object, whether a Python object or not, that implements the abstraction 
of a namespace. At module scope,

  name = ob
is the same as
  globals()['name']=ob
Within a class statement, substitute 'class-dict' for 'globals'
Within functions, CPython uses an internal array, so
  name = ob
becomes
  locals_array[name-number] = ob

Or, to put it another way, Python dicts and lists are, considered 
abstractly, associations also, just like namespaces. Dicts are more 
general than namespaces, sequences are 'number-spaces' instead of 
name-spaces.


Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list