[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.python

along the lines, hash and obj. id.

Aaron Brady

2/26/2008 1:55:00 AM

I'd like to do this:

a= list( range( 5 ) )
assert a== [ 0, 1, 2, 3, 4 ]
for i in ref( a ):
i.ref*= 2
a= deref( a )
assert a== [ 0, 2, 4, 6, 8 ]

In the for loop, i objects maintain their identities, while still
being reassigned. The first way I think of is this:

class Ref:
def __init__( self, ref ):
self.ref= ref
def __repr__( self ):
return '<Ref %r>'% self.ref

def ref( it ):
for i, e in enumerate( it ):
it[i]= Ref(e)
return it

def deref( it ):
return [ i.ref for i in it ]

Dictionaries, sets, and the primitives all have ways to do this, in
particular, to reset them: a= {} is equivalent to a.clear(), except
that other references to it corefer before, and in the former, don't
after.

class A:
def __init__( self, d ):
self.d= d

d= {}
a= A( d )
d= {}

is different than:

d= {}
a= A( d )
d.clear()

a.d still refers to d in the second, whereas the identity is broken in
the first.

Can perhaps a subclass of List return references to its elements, so
that L[2] is L[2], even if you assign it to a different value later,
and even in the case of integers.?

(*This came out a little funny.)
7 Answers

Dennis Lee Bieber

2/26/2008 5:31:00 AM

0

On Mon, 25 Feb 2008 17:55:18 -0800 (PST), castironpi@gmail.com declaimed
the following in comp.lang.python:

> I'd like to do this:
>
> a= list( range( 5 ) )
> assert a== [ 0, 1, 2, 3, 4 ]
> for i in ref( a ):
> i.ref*= 2
> a= deref( a )
> assert a== [ 0, 2, 4, 6, 8 ]
>
> In the for loop, i objects maintain their identities, while still
> being reassigned. The first way I think of is this:
>

Please reread the Python references describing:

Mutable;
Immutable;
Name binding to objects

Numbers, tuples, and strings are IMMUTABLE... There is no way to
change the value of a number object, string object, or tuple object. One
can only rebind the name to a new object containing the desired value.

>>> a = 1 + 3
>>> b = 4
>>> id(a)
3301380
>>> id(b)
3301380
>>> id(4)
3301380
>>>

Dictionaries, lists, and, I presume, sets are MUTABLE... The
contents can be modified in-place... Note that such modifications most
likely result in changing internal references.

>>> l = [ 0, 1, 3, 5 ]
>>> for i, itm in enumerate(l):
.... print id(itm), id(l[i])
....
3301428 3301428
3301416 3301416
3301392 3301392
3301368 3301368
>>> l[1] = l[1] + 3
>>> for i, itm in enumerate(l):
.... print id(itm), id(l[i])
....
3301428 3301428
3301380 3301380
3301392 3301392
3301368 3301368
>>>

> Dictionaries, sets, and the primitives all have ways to do this, in
> particular, to reset them: a= {} is equivalent to a.clear(), except
> that other references to it corefer before, and in the former, don't
> after.
>
No, it is NOT equivalent.

a = {} CREATES a NEW, EMPTY dictionary, disconnects the name "a" (if it
is in existance prior to this point) from whatever object it is bound
to, and connects it to the new dictionary.

a.clear() is a mutating function that goes /into/ the existing "a" and
modifies its contents.

>>> del a
>>> id(a)
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
NameError: name 'a' is not defined
>>> a.clear()
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
NameError: name 'a' is not defined
>>> a = { "some" : "dictionary", "object" : "for test" }
>>> a
{'object': 'for test', 'some': 'dictionary'}
>>> id(a)
18390304
>>> a.clear()
>>> id(a)
18390304
>>> a = {}
>>> id(a)
18387280
>>>
--
Wulfraed Dennis Lee Bieber KD6MOG
wlfraed@ix.netcom.com wulfraed@bestiaria.com
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: web-asst@bestiaria.com)
HTTP://www.bestiaria.com/

Aaron Brady

2/26/2008 7:59:00 AM

0

On Feb 25, 11:30 pm, Dennis Lee Bieber <wlfr...@ix.netcom.com> wrote:
> On Mon, 25 Feb 2008 17:55:18 -0800 (PST), castiro...@gmail.com declaimed
> the following in comp.lang.python:
>
> > I'd like to do this:
>
> > a= list( range( 5 ) )
> > assert a== [ 0, 1, 2, 3, 4 ]
> > for i in ref( a ):
> >     i.ref*= 2
> > a= deref( a )
> > assert a== [ 0, 2, 4, 6, 8 ]

[snip]

> > Dictionaries, sets, and the primitives all have ways to do this, in
> > particular, to reset them: a= {} is equivalent to a.clear(), except

<em>EXCEPT THAT</em>

> > that other references to it corefer before, and in the former, don't
> > after.

No, ={} and .clear() are not equivalent.

In the case of class instances,

>>> class Instance(): pass
...
>>> obj= Instance()
>>> obj.a= {}
>>> d= obj.a
>>> obj.a[0]= object()
>>> d[0]
<object object at 0x00A37468>
>>> e= obj
>>> obj.a= {}
>>> d
{0: <object object at 0x00A37468>}
>>> e.a
{}

It works to keep a reference to the object, then access the member
again. If your only reference to the object is the member itself,
obj.a= {} breaks d, but obj.a.clear() keeps it alive.

In the case of immutables, there is no such .clear() equivalent. If
obj.a is a tuple, string, or integer (*miss any?), d is always broken
when obj.a is changed.

The generic solution involves a second level of indirection: tuple* d=
&obj.a. I can't land a clean solution to it though.

Dennis Lee Bieber

2/26/2008 7:11:00 PM

0

On Mon, 25 Feb 2008 23:58:52 -0800 (PST), castironpi@gmail.com declaimed
the following in comp.lang.python:

> The generic solution involves a second level of indirection: tuple* d=
> &obj.a. I can't land a clean solution to it though.

And you wont, because the capability would break Python's
immutability rules.

If you really want to play with pointers, write in C...
--
Wulfraed Dennis Lee Bieber KD6MOG
wlfraed@ix.netcom.com wulfraed@bestiaria.com
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: web-asst@bestiaria.com)
HTTP://www.bestiaria.com/

Aaron Brady

2/27/2008 2:55:00 AM

0

On Feb 26, 1:11 pm, Dennis Lee Bieber <wlfr...@ix.netcom.com> wrote:
> On Mon, 25 Feb 2008 23:58:52 -0800 (PST), castiro...@gmail.com declaimed
> the following in comp.lang.python:
>
> > The generic solution involves a second level of indirection: tuple* d=
> > &obj.a.  I can't land a clean solution to it though.
>
>         And you wont, because the capability would break Python's
> immutability rules.
>
>         If you really want to play with pointers, write in C...
> --
>         Wulfraed        Dennis Lee Bieber               KD6MOG
>         wlfr...@ix.netcom.com             wulfr...@bestiaria.com
>                 HTTP://wlfraed.home.netcom.com/
>         (Bestiaria Support Staff:               web-a...@bestiaria.com)
>                 HTTP://www.bestiaria.com/

I confess, sometimes I pass a one-length list to a function, just so
it can modify in-place.

Gabriel Genellina

2/27/2008 10:16:00 PM

0

En Tue, 26 Feb 2008 05:58:52 -0200, <castironpi@gmail.com> escribió:

> It works to keep a reference to the object, then access the member
> again. If your only reference to the object is the member itself,
> obj.a= {} breaks d, but obj.a.clear() keeps it alive.
>
> In the case of immutables, there is no such .clear() equivalent. If
> obj.a is a tuple, string, or integer (*miss any?), d is always broken
> when obj.a is changed.

"when obj.a is changed": That may have two meanings:

a) "when the object itself referenced by obj.a is modified" or
b) "when obj.a is made to refer to another object"

For a), you use something like obj.a.somemethod(). "obj.a" still refers to
the same object, even if it changed internally; if obj.a and foo.bar both
were refering to the same object, they still do. [1]
For b), you have to rebind the name using any statement with such effects
(assignment, for, with, import...); in this example, as obj.a is an
attribute reference, the only allowed forms are assignments: obj.a =
something (including augmented assignments obj.a += something). If obj.a
and foo.bar both were previously refering to the same object, you can't
guarantee that after executing such statements.

> The generic solution involves a second level of indirection: tuple* d=
> &obj.a. I can't land a clean solution to it though.

(Forget about C and pointers... you'll just confuse things this way.
Python has objects and names that refer to them, not pointers and
variables with allocated storage and type.)

Depending on the requirements, there are several answers. You may
distinghish "some" place as "the" official place where the object lives,
and make all other retrieve it from there when needed. Or use a
notification mechanism when its value changes. Or wrap the value into
another shared object.

[1] Assuming somemethod() isn't evil and rebinds obj.a itself...

--
Gabriel Genellina

Aaron Brady

2/27/2008 11:38:00 PM

0

On Feb 27, 4:16 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
> En Tue, 26 Feb 2008 05:58:52 -0200, <castiro...@gmail.com> escribió:
>
> > It works to keep a reference to the object, then access the member
> > again. If your only reference to the object is the member itself,
> > obj.a= {} breaks d, but obj.a.clear() keeps it alive.
>
> > In the case of immutables, there is no such .clear() equivalent.

Reemphisize:

> > If obj.a is a tuple, string, or integer.

Very important for the deduction. /IF/ it /IS/.

> > [THEN] d is always broken when obj.a is changed.

> "when obj.a is changed": That may have two meanings:
>
> a) "when the object itself referenced by obj.a is modified" or
> b) "when obj.a is made to refer to another object"

Since obj.a is immutable, (b) is guaranteed for any change.

... Unless what you're saying is, 'this guy sucks with words.' In
that case, <sighs, bows, shakes head, sulks>. Make that, "when obj.a
is -rebound-," and it can't be changed at all.

> For a), you use something like obj.a.somemethod(). "obj.a" still refers to
> the same object, even if it changed internally; if obj.a and foo.bar both
> were refering to the same object, they still do. [1]
> For b), you have to rebind the name using any statement with such effects
> (assignment, for, with, import...); in this example, as obj.a is an
> attribute reference, the only allowed forms are assignments: obj.a =
> something (including augmented assignments obj.a += something). If obj.a
> and foo.bar both were previously refering to the same object, you can't
> guarantee that after executing such statements.
>
> > The generic solution involves a second level of indirection: tuple* d=
> > &obj.a. I can't land a clean solution to it though.
>
> (Forget about C and pointers... you'll just confuse things this way.
> Python has objects and names that refer to them, not pointers and
> variables with allocated storage and type.)
>
> Depending on the requirements, there are several answers. You may
> distinghish "some" place as "the" official place where the object lives,
> and make all other retrieve it from there when needed.

While this breaks encapsulation, it may mean the right thing
sometimes.

> Or use a
> notification mechanism when its value changes.

Then, not only do "you" rebind a, but "everyone else" does too. IOW,
not only does the target rebind a, but all the Notify-ees / Observers
have to rebind their slates.

> Or wrap the value into another shared object.

Probably the most general.

Call it ReftoImmutable. a= ref( ( 2, ) ); b= a; a.val= ( 3, ); assert
b.val== ( 3, ). You still can't use a.val in sets, but you can use
a. assert b in { a: True }, since assert b== a.

> [1] Assuming somemethod() isn't evil and rebinds obj.a itself...

(<cough cough>)

However, it can get a little tedious. RefToImmutableList is the next
step on the road, which takes a list, and makes its elements
RefToImmutable instances. You can call a function on rtiList[n], and
it can still set the element there: elem.val= 0, elem.val+= 1, &c., in
cases in which it's better than passing a ( list, index ) pair. You
have to know that rtiElem is a RefToImmutable in the former, but you
had to know the meaning of list and index in the latter too. And as
mutables can be stored in rti.val too, you can always just call them
ref.

In other news, ? is also "not used in Python. [Its] occurrence outside
string literals and comments is an unconditional error:". Reserved
for the next function decorators. <evil cackle>


Aaron Brady

3/3/2008 2:51:00 AM

0

On Feb 27, 5:38 pm, castiro...@gmail.com wrote:
> On Feb 27, 4:16 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
> > For a), you use something like obj.a.somemethod(). "obj.a" still refers to
> > the same object, even if it changed internally; if obj.a and foo.bar both
> > were refering to the same object, they still do. [1]
> > Or wrap the value into another shared object.
> it can still set the element there: elem.val= 0, elem.val+= 1, &c., in

Following obj.a.val is foo.bar.val and obj.a is foo.bar, you can also
get away with a= A(); a.c.val= 2; assert A.c.val== 2.