[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

lists of variables

Michael Pardee

2/21/2010 3:25:00 AM

I'm relatively new to python and I was very surprised by the following behavior:

>>> a=1
>>> b=2
>>> mylist=[a,b]
>>> print mylist
[1, 2]
>>> a=3
>>> print mylist
[1, 2]

Whoah! Are python lists only for literals? Nope:

>>> c={}
>>> d={}
>>> mydlist=[c,d]
>>> print mydlist
[{}, {}]
>>> c['x']=1
>>> print mydlist
[{'x': 1}, {}]

So it looks like variables in a list are stored as object references.
This seems to confirm that:

mydlist[1]['y']=4
>>> print mydlist
[{}, {'y': 4}]

So I figure my initial example doesn't work because if you assign a
literal to something it is changing the object. But modifying a list
or dict (as long as you don't re-construct it) does not change the
object.

I can think of some ways to work around this, including using single
element lists as "pointers":

>>> aa=[1]
>>> bb=[2]
>>> myplist=[aa,bb]
>>> print myplist
[[1], [2]]
>>> aa[0]=3
>>> print myplist
[[3], [2]]


But what would be "the python way" to accomplish "list of variables"
functionality?
11 Answers

Ben Finney

2/21/2010 4:09:00 AM

0

Michael Pardee <python-list@open-sense.com> writes:

> But what would be "the python way" to accomplish "list of variables"
> functionality?

You'll need to explain what â??list of variablesâ? functionality is.

If you mean â??collection of name-to-value mappingsâ?, the native mapping
type in Python is â??dictâ??. If that doesn't meet your needs, you'll need
to be more specific about what behaviour you want.

--
\ â??Most people don't realize that large pieces of coral, which |
`\ have been painted brown and attached to the skull by common |
_o__) wood screws, can make a child look like a deer.â? â??Jack Handey |
Ben Finney

Steven D'Aprano

2/21/2010 4:21:00 AM

0

On Sat, 20 Feb 2010 21:25:19 -0600, Michael Pardee wrote:

> I'm relatively new to python and I was very surprised by the following
> behavior:
[snip]

I don't see why. It's fairly unusual behaviour to want, and it would be
surprising if you did this:

def test():
x = 1
mylist = [2, 4, x]
function(mylist)
assert x == 1

and the assertion failed, even though you never passed x to the function.
Such behaviour could easily turn into a never-ending source of bugs.


> So it looks like variables in a list are stored as object references.

Python doesn't store variables in lists, it stores objects, always.

Even Python variables aren't variables *grin*, although it's really
difficult to avoid using the term. Python variables are mappings between
names (strings) and objects, not memory locations.


> So I figure my initial example doesn't work because if you assign a
> literal to something it is changing the object. But modifying a list or
> dict (as long as you don't re-construct it) does not change the object.

Yes, we talk about name binding (and rebinding) versus mutation. A simple
example:

>>> alist = blist = [] # bind two names to the same list object
>>> alist.append(1) # mutate the list (modify in place)
>>> blist
[1]


>>> alist = alist + [2] # a rebinding operation
>>> blist
[1]
>>> alist
[1, 2]


> I can think of some ways to work around this, including using single
> element lists as "pointers":

Yes, that's a standard way to do it, except that by "standard" I mean
"really really really rare, honestly, hardly anyone does that".

Slightly less rare, but still uncommon, is to wrap objects in an instance:

class Record:
pass

o = Record()
o.x = 1
o.y = 2
modify(o)
print o.x, o.y

Of course you can make the class as fancy, or as simple, as you want.

But a better approach is to take advantage of Python's ability to return
multiple values:

x = 1
y = 2
x, y = modify(x, y)

rather than:

x = 1
y = 2
modify([x, y])


Speaking as an old Pascal coder, you won't miss pass-by-reference very
often.




--
Steven

Carl Banks

2/21/2010 6:32:00 AM

0

On Feb 20, 7:25 pm, Michael Pardee <python-l...@open-sense.com> wrote:
> I'm relatively new to python and I was very surprised by the following behavior:
>
> >>> a=1
> >>> b=2
> >>> mylist=[a,b]
> >>> print mylist
> [1, 2]
> >>> a=3
> >>> print mylist
>
> [1, 2]
>
> Whoah!  Are python lists only for literals?  Nope:
>
> >>> c={}
> >>> d={}
> >>> mydlist=[c,d]
> >>> print mydlist
> [{}, {}]
> >>> c['x']=1
> >>> print mydlist
>
> [{'x': 1}, {}]
>
> So it looks like variables in a list are stored as object references.
> This seems to confirm that:
>
> mydlist[1]['y']=4>>> print mydlist
>
> [{}, {'y': 4}]
>
> So I figure my initial example doesn't work because if you assign a
> literal to something it is changing the object.  But modifying a list
> or dict (as long as you don't re-construct it) does not change the
> object.

All correct, very observant for a Python newbie.

To be more

immutable



> I can think of some ways to work around this, including using single
> element lists as "pointers":
>
> >>> aa=[1]
> >>> bb=[2]
> >>> myplist=[aa,bb]
> >>> print myplist
> [[1], [2]]
> >>> aa[0]=3
> >>> print myplist
>
> [[3], [2]]
>
> But what would be "the python way" to accomplish "list of variables"
> functionality?

Python doesn't have variable references (except in a limited way; see
below), so unless you want to use lists as pointers, I'd recommend
rethinking the problem. Occasionally I feel like I'd like to be able
to do this, but usually another way exists that is, at worst, slightly
more complex.

For some cases the easiest thing is to make all the variables you're
interested in listing attributes of an object (or values of a dict).
Then store a list of names (or keys).

class X(object): pass
x = X()
x.foo = 1
x.bar = 2
s = ["foo","bar"]
setattr(x,s[0],3)
print x.foo # prints 3

A rule of thumb in deciding whether to use attributes is whether you
will typically know their names in your code ahead of time; if so
storing the values as attributes is a good idea. If you are inputing
or calculating the names, then it's better to use a dict.


** The one place where Python does have references is when accessing
variables in an enclosing scope (not counting module-level). But
these references aren't objects, so you can't store them in a list, so
it can't help you:

def f():
s = []
a = 1
def g():
print a
s.append(a)
g() # prints 1
a = 2
g() # prints 2: g's a is a reference to f's a
print s # prints [1,2] not [2,2]


Carl Banks

Steven D'Aprano

2/21/2010 6:50:00 AM

0

On Sat, 20 Feb 2010 22:31:44 -0800, Carl Banks wrote:

> The one place where Python does have references is when accessing
> variables in an enclosing scope (not counting module-level).

What makes you say that?

> But these
> references aren't objects, so you can't store them in a list, so it
> can't help you:

I don't even understand this. Your own example clearly shows that the are
objects and you can store them in a list, so I have no understanding of
what you mean.


> def f():
> s = []
> a = 1
> def g():
> print a

a is a name bound to an object which inherits a __str__ method, hence you
can print it.

> s.append(a)

a is bound to an object you can put in a list.

> g() # prints 1
> a = 2
> g() # prints 2: g's a is a reference to f's a
> print s # prints [1,2] not [2,2]

Yes, you are correct that lexical scoping doesn't allow the OP to embed
references to names in lists. I'm just confused why you think that
lexical scoping is equivalent to references that can't be put in lists,
or why you think this behaviour is any different from lexical scoping
everywhere else?

# Instead of two scopes, f and g, use two scopes, the module (global)
# and local scope g:
s = []
a = 1
def g():
print a
s.append(a)

g() # prints 1
a = 2
g() # prints 2: g's a is a reference to the global a
print s # prints [1,2] not [2,2]


There is no difference between lexical scoping between a function and a
nested function, and the lexical scoping between the global namespace and
a nested function.



--
Steven

Carl Banks

2/21/2010 7:44:00 AM

0

On Feb 20, 10:50 pm, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.au> wrote:
> On Sat, 20 Feb 2010 22:31:44 -0800, Carl Banks wrote:
> > The one place where Python does have references is when accessing
> > variables in an enclosing scope (not counting module-level).  
>
> What makes you say that?
>
> > But these
> > references aren't objects, so you can't store them in a list, so it
> > can't help you:
>
> I don't even understand this. Your own example clearly shows that the are
> objects and you can store them in a list, so I have no understanding of
> what you mean.
>
> > def f():
> >     s = []
> >     a = 1
> >     def g():
> >         print a
>
> a is a name bound to an object which inherits a __str__ method, hence you
> can print it.
>
> >         s.append(a)
>
> a is bound to an object you can put in a list.
>
> >     g() # prints 1
> >     a = 2
> >     g() # prints 2: g's a is a reference to f's a
> >     print s # prints [1,2] not [2,2]
>
> Yes, you are correct that lexical scoping doesn't allow the OP to embed
> references to names in lists. I'm just confused why you think that
> lexical scoping is equivalent to references that can't be put in lists,
> or why you think this behaviour is any different from lexical scoping
> everywhere else?
>
> # Instead of two scopes, f and g, use two scopes, the module (global)
> # and local scope g:
> s = []
> a = 1
> def g():
>     print a
>     s.append(a)
>
> g() # prints 1
> a = 2
> g() # prints 2: g's a is a reference to the global a
> print s # prints [1,2] not [2,2]
>
> There is no difference between lexical scoping between a function and a
> nested function, and the lexical scoping between the global namespace and
> a nested function.


http://tinyurl...



Carl Banks

Lie Ryan

2/21/2010 10:25:00 AM

0

On 02/21/10 15:21, Steven D'Aprano wrote:
>> > So it looks like variables in a list are stored as object references.
> Python doesn't store variables in lists, it stores objects, always.
>
> Even Python variables aren't variables *grin*, although it's really
> difficult to avoid using the term. Python variables are mappings between
> names (strings) and objects, not memory locations.

Actually, no programming languages have used the term "variable"
correctly, as per its original mathematical definition.

Steven D'Aprano

2/21/2010 11:18:00 AM

0

On Sat, 20 Feb 2010 23:44:29 -0800, Carl Banks wrote:

> On Feb 20, 10:50 pm, Steven D'Aprano <st...@REMOVE-THIS-
> cybersource.com.au> wrote:

>> What makes you say that?
[...]
>> I don't even understand this.
[...]
>> I'm just confused why you think that
>> lexical scoping is equivalent to references that can't be put in lists,
>> or why you think this behaviour is any different from lexical scoping
>> everywhere else?

> http://tinyurl...

Ha ha ha, very amusing. But I was genuinely confused, because I know
you're an experienced Python coder and not some n00b, so I thought maybe
you were referring to something that escaped me. Your response, apt
though it may be, does nothing to clear up my confusion.

Presumably if you had a serious response you would have made it, so I'll
chalk it up to a generalised confusion field.

*wink*


--
Steven

Bartc

2/21/2010 9:55:00 PM

0


"Michael Pardee" <python-list@open-sense.com> wrote in message
news:mailman.22.1266722722.4577.python-list@python.org...
> I'm relatively new to python and I was very surprised by the following
> behavior:
>
>>>> a=1
>>>> b=2
>>>> mylist=[a,b]
>>>> print mylist
> [1, 2]
>>>> a=3
>>>> print mylist
> [1, 2]
>
> Whoah! Are python lists only for literals? Nope:
>
>>>> c={}
>>>> d={}
>>>> mydlist=[c,d]
>>>> print mydlist
> [{}, {}]
>>>> c['x']=1
>>>> print mydlist
> [{'x': 1}, {}]
>
> So it looks like variables in a list are stored as object references.
> This seems to confirm that:
>
> mydlist[1]['y']=4
>>>> print mydlist
> [{}, {'y': 4}]
>
> So I figure my initial example doesn't work because if you assign a

That shows a different outlook. I would have said your first example works
as expected and it was the second example that was strange, possibly due to
shallow instead of deep copies by Python.

--
Bartc

Gregory Ewing

2/21/2010 11:33:00 PM

0

Steven D'Aprano wrote:
> On Sat, 20 Feb 2010 22:31:44 -0800, Carl Banks wrote:
>
>>The one place where Python does have references is when accessing
>>variables in an enclosing scope (not counting module-level).
>
> What makes you say that?

I think Carl is talking about cells, which *are* actually objects
(in CPython at least), but they're internal details of the
interpreter, and you can't do anything useful with them from
Python code.

--
Greg

aahz

2/26/2010 7:23:00 PM

0

In article <mailman.22.1266722722.4577.python-list@python.org>,
Michael Pardee <python-list@open-sense.com> wrote:
>
>I'm relatively new to python and I was very surprised by the following
>behavior:

http://starship.python.net/crew/mwh/hacks/object...
--
Aahz (aahz@pythoncraft.com) <*> http://www.python...

"Many customs in this life persist because they ease friction and promote
productivity as a result of universal agreement, and whether they are
precisely the optimal choices is much less important." --Henry Spencer