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


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

How to isolate a constant?

Started byGnarlodious <gnarlodious@gmail.com>
First post2011-10-22 17:26 -0700
Last post2011-10-22 17:55 -0700
Articles 13 — 10 participants

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


Contents

  How to isolate a constant? Gnarlodious <gnarlodious@gmail.com> - 2011-10-22 17:26 -0700
    Re: How to isolate a constant? Chris Rebert <clp2@rebertia.com> - 2011-10-22 17:41 -0700
      Re: How to isolate a constant? Gnarlodious <gnarlodious@gmail.com> - 2011-10-22 18:01 -0700
        Re: How to isolate a constant? 88888 Dihedral <dihedral88888@googlemail.com> - 2011-10-22 22:12 -0700
        Re: How to isolate a constant? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-10-23 05:32 +0000
        Re: How to isolate a constant? Paul Rudin <paul.nospam@rudin.co.uk> - 2011-10-23 11:23 +0100
    Re: How to isolate a constant? MRAB <python@mrabarnett.plus.com> - 2011-10-23 01:46 +0100
      Re: How to isolate a constant? Alan Meyer <ameyer2@yahoo.com> - 2011-10-25 15:50 -0400
        Re: How to isolate a constant? Ian Kelly <ian.g.kelly@gmail.com> - 2011-10-25 14:05 -0600
        Re: How to isolate a constant? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2011-10-25 17:08 -0700
          Re: How to isolate a constant? Mel <mwilson@the-wire.com> - 2011-10-25 22:48 -0400
        Re: How to isolate a constant? Ian Kelly <ian.g.kelly@gmail.com> - 2011-10-25 18:30 -0600
    Re: How to isolate a constant? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2011-10-22 17:55 -0700

#14856 — How to isolate a constant?

FromGnarlodious <gnarlodious@gmail.com>
Date2011-10-22 17:26 -0700
SubjectHow to isolate a constant?
Message-ID<f5539538-d079-4be1-b2c0-d98d3fc6a33f@h39g2000prh.googlegroups.com>
Say this:

class tester():
	_someList = [0, 1]
	def __call__(self):
		someList = self._someList
		someList += "X"
		return someList

test = tester()

But guess what, every call adds to the variable that I am trying to
copy each time:
test()
> [0, 1, 'X']
test()
> [0, 1, 'X', 'X']


Can someone explain this behavior? And how to prevent a classwide
constant from ever getting changed?

-- Gnarlie

[toc] | [next] | [standalone]


#14857

FromChris Rebert <clp2@rebertia.com>
Date2011-10-22 17:41 -0700
Message-ID<mailman.2137.1319330487.27778.python-list@python.org>
In reply to#14856
On Sat, Oct 22, 2011 at 5:26 PM, Gnarlodious <gnarlodious@gmail.com> wrote:
> Say this:
>
> class tester():

Style note: either have it explicitly subclass `object`, or don't
include the parens at all. Empty parens for the superclasses is just
weird.

>        _someList = [0, 1]
>        def __call__(self):
>                someList = self._someList
>                someList += "X"
>                return someList
>
> test = tester()
>
> But guess what, every call adds to the variable that I am trying to
> copy each time:
> test()
>> [0, 1, 'X']
> test()
>> [0, 1, 'X', 'X']
>
>
> Can someone explain this behavior?

The line `someList = self._someList` does NOT copy the list. It make
`someList` point to the same existing list object. Hence,
modifications to that object from either variable will affect the
other.
Similarly, `someList += "X"` modifies someList *in-place*; it does not
produce a new list object.

The upshot is that you're just modifying and returning references to
*the same list* repeatedly, never producing a new list object.

> And how to prevent a classwide
> constant from ever getting changed?

Python doesn't have any language-enforced notion of constants. So,
short of writing/using a library to try and enforce such a notion,
you're out of luck. You could use an immutable datatype (e.g. a tuple)
instead of a mutable one (e.g. a list) as some level of safeguard
though.

Cheers,
Chris
--
http://rebertia.com

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


#14860

FromGnarlodious <gnarlodious@gmail.com>
Date2011-10-22 18:01 -0700
Message-ID<7840d89c-3648-45fe-ae6f-d3bb2ca2abdb@z28g2000pro.googlegroups.com>
In reply to#14857
On Oct 22, 6:41 pm, Chris Rebert <c...@rebertia.com> wrote:

> The line `someList = self._someList` does NOT copy the list. It make
> `someList` point to the same existing list object.
Thanks for all those explanations, I've already fixed it with a tuple.
Which is more reliable anyway.

-- Gnarlie

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


#14863

From88888 Dihedral <dihedral88888@googlemail.com>
Date2011-10-22 22:12 -0700
Message-ID<12317784.900.1319346736804.JavaMail.geo-discussion-forums@prfk19>
In reply to#14860
Thank you for the  good trick for  a  static class owned property.  Someone might object this but this is really useful.

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


#14864

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-10-23 05:32 +0000
Message-ID<4ea3a707$0$29968$c3e8da3$5496439d@news.astraweb.com>
In reply to#14860
On Sat, 22 Oct 2011 18:01:52 -0700, Gnarlodious wrote:

> On Oct 22, 6:41 pm, Chris Rebert <c...@rebertia.com> wrote:
> 
>> The line `someList = self._someList` does NOT copy the list. It make
>> `someList` point to the same existing list object.
> Thanks for all those explanations, I've already fixed it with a tuple.
> Which is more reliable anyway.

No, tuples are not "more reliable" than lists. Don't make the mistake of 
confusing your inexperience and lack of understanding about Python's 
object model for "lists are unreliable". They are completely reliable. 
You just have to learn how they work, and not make invalid assumptions 
about how they work.

You wouldn't say "Nails are more reliable than screws, because I hammered 
a screw into a plaster wall and it just fell out." Of course it fell out: 
you used it incorrectly for what you needed.


-- 
Steven

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


#14868

FromPaul Rudin <paul.nospam@rudin.co.uk>
Date2011-10-23 11:23 +0100
Message-ID<87y5wcj9at.fsf@no-fixed-abode.cable.virginmedia.net>
In reply to#14860
Gnarlodious <gnarlodious@gmail.com> writes:

> Thanks for all those explanations, I've already fixed it with a tuple.
> Which is more reliable anyway.

neither of lists or tuples are "more reliable" than the other. They both
have perfectly well defined behaviour (which can be gleaned from reading
the documentation) and reliably behave as documented. You just have to
choose which fits better for the computation you're trying to implement.

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


#14858

FromMRAB <python@mrabarnett.plus.com>
Date2011-10-23 01:46 +0100
Message-ID<mailman.2138.1319330815.27778.python-list@python.org>
In reply to#14856
On 23/10/2011 01:26, Gnarlodious wrote:
> Say this:
>
> class tester():
> 	_someList = [0, 1]
> 	def __call__(self):
> 		someList = self._someList
> 		someList += "X"
> 		return someList
>
> test = tester()
>
> But guess what, every call adds to the variable that I am trying to
> copy each time:
> test()
>> [0, 1, 'X']
> test()
>> [0, 1, 'X', 'X']
>
>
> Can someone explain this behavior? And how to prevent a classwide
> constant from ever getting changed?
>
'_someList' is part of the class itself.

This:

     someList = self._someList

just creates a new _reference to the list and this:

     someList += "X"

appends the items of the sequence "X" to the list.

Note that a string is also a sequence of characters, so:

 >>> x = []
 >>> x += "XY"
 >>> x
['X', 'Y']

Python will copy something only when you tell it to copy. A simple way
of copying a list is to slice it:

     someList = self._someList[:]

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


#14979

FromAlan Meyer <ameyer2@yahoo.com>
Date2011-10-25 15:50 -0400
Message-ID<4EA71323.2030500@yahoo.com>
In reply to#14858
On 10/22/2011 8:46 PM, MRAB wrote:
> On 23/10/2011 01:26, Gnarlodious wrote:
>> Say this:
>>
>> class tester():
>> _someList = [0, 1]
>> def __call__(self):
>> someList = self._someList
>> someList += "X"
>> return someList
>>
>> test = tester()
>>
>> But guess what, every call adds to the variable that I am trying to
>> copy each time:
>> test()
>>> [0, 1, 'X']
>> test()
>>> [0, 1, 'X', 'X']
...
> Python will copy something only when you tell it to copy. A simple way
> of copying a list is to slice it:
>
> someList = self._someList[:]

And another simple way:

     ...
     someList = list(self._someList)
     ...

Alan

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


#14980

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-10-25 14:05 -0600
Message-ID<mailman.2215.1319573187.27778.python-list@python.org>
In reply to#14979
On Tue, Oct 25, 2011 at 1:50 PM, Alan Meyer <ameyer2@yahoo.com> wrote:
>> Python will copy something only when you tell it to copy. A simple way
>> of copying a list is to slice it:
>>
>> someList = self._someList[:]
>
> And another simple way:
>
>    ...
>    someList = list(self._someList)
>    ...

I generally prefer the latter.  It's clearer, and it guarantees that
the result will be a list, which is usually what you want in these
situations, rather than whatever unexpected type was passed in.

Cheers,
Ian

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


#14988

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2011-10-25 17:08 -0700
Message-ID<mailman.2219.1319587711.27778.python-list@python.org>
In reply to#14979
On Tue, 25 Oct 2011 14:05:49 -0600, Ian Kelly <ian.g.kelly@gmail.com>
declaimed the following in gmane.comp.python.general:

> On Tue, Oct 25, 2011 at 1:50 PM, Alan Meyer <ameyer2@yahoo.com> wrote:
> >> Python will copy something only when you tell it to copy. A simple way
> >> of copying a list is to slice it:
> >>
> >> someList = self._someList[:]
> >
> > And another simple way:
> >
> >    ...
> >    someList = list(self._someList)
> >    ...
> 
> I generally prefer the latter.  It's clearer, and it guarantees that
> the result will be a list, which is usually what you want in these
> situations, rather than whatever unexpected type was passed in.
> 

Where's the line form to split those who'd prefer the first vs the
second result in this sample <G>:

>>> unExpected = "What about a string"
>>> firstToLast = unExpected[:]
>>> repr(firstToLast)
"'What about a string'"
>>> explicitList = list(unExpected)
>>> repr(explicitList)
"['W', 'h', 'a', 't', ' ', 'a', 'b', 'o', 'u', 't', ' ', 'a', ' ', 's',
't', 'r', 'i', 'n', 'g']"
>>> 
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
        wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

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


#14992

FromMel <mwilson@the-wire.com>
Date2011-10-25 22:48 -0400
Message-ID<j87sdc$o8$1@speranza.aioe.org>
In reply to#14988
Dennis Lee Bieber wrote:

> Where's the line form to split those who'd prefer the first vs the
> second result in this sample <G>:
> 
>>>> unExpected = "What about a string"
>>>> firstToLast = unExpected[:]
>>>> repr(firstToLast)
> "'What about a string'"
>>>> explicitList = list(unExpected)
>>>> repr(explicitList)
> "['W', 'h', 'a', 't', ' ', 'a', 'b', 'o', 'u', 't', ' ', 'a', ' ', 's',
> 't', 'r', 'i', 'n', 'g']"
>>>> 

Well, as things stand, there's a way to get whichever result you need.  The 
`list` constructor builds a single list from a single iterable.  The list 
literal enclosed by `[`, `]` makes a list containing a bunch of items.

Strings being iterable introduces a wrinkle, but `list('abcde')` doesn't 
create `['abcde']` just as `list(1)` doesn't create `[1]`.

	Mel.

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


#14990

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-10-25 18:30 -0600
Message-ID<mailman.2221.1319589064.27778.python-list@python.org>
In reply to#14979
On Tue, Oct 25, 2011 at 6:08 PM, Dennis Lee Bieber
<wlfraed@ix.netcom.com> wrote:
> Where's the line form to split those who'd prefer the first vs the
> second result in this sample <G>:
>
>>>> unExpected = "What about a string"
>>>> firstToLast = unExpected[:]

Strings are immutable.  That doesn't suffice to copy them, even
assuming you would want to do so in the first place.

>>> unExpected is firstToLast
True

If you find yourself needing to make a copy, that usually means that
you plan on modifying either the original or the copy, which in turn
means that you need a type that supports modification operations,
which usually means a list.  If you pass in a string and then copy it
with [:] and then try to modify it, you'll get an exception.  If you
don't try to modify it, then you probably didn't need to copy it in
the first place.

Cheers,
Ian

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


#14859

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2011-10-22 17:55 -0700
Message-ID<mailman.2139.1319331340.27778.python-list@python.org>
In reply to#14856
On Sat, 22 Oct 2011 17:26:22 -0700 (PDT), Gnarlodious
<gnarlodious@gmail.com> declaimed the following in
gmane.comp.python.general:

> Say this:
> 
> class tester():
> 	_someList = [0, 1]
> 	def __call__(self):
> 		someList = self._someList
> 		someList += "X"
> 		return someList
> 
> test = tester()
> 
> But guess what, every call adds to the variable that I am trying to
> copy each time:

	You never copied it... You just created a temporary local reference
to the same object

	_someList = [0, 1]

creates a mutable list object containing two elements; it then binds the
/name/ "_someList" to that object.

	someList = self._someList

finds the OBJECT to which "self._someList" is bound, and binds a second
name "someList" to the same object.

	someList += "X"

retrieves the OBJECT to which "someList" is bound, mutates it by
appending an "X".

	Nowhere do you ever create a NEW list object. Try

	someList = self._someList[:]

which finds the object to which "self._someList" is bound, extracts a
sublist [:] (from first element to last element) -- this is a NEW list
-- and binds "someList" to that new object.

> Can someone explain this behavior? And how to prevent a classwide
> constant from ever getting changed?

	"Ever"? Can't really be done with Python -- if you know it exists,
you can get to it and rebind it, or mutate it if it is a mutable object.
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
        wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [standalone]


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


csiph-web