object references

D

DrConti

Dear Python developer community,
I'm quite new to Python, so perhaps my question is well known and the
answer too.

I need a variable alias ( what in other languages you would call "a
pointer" (c) or "a reference" (perl))
I read some older mail articles and I found that the offcial position
about that was that variable referencing wasn't implemented because
it's considered bad style.
There was also a suggestion to write a real problem where referencing
is really needed.
I have one...:

I'm trying to generate dynamically class methods which works on
predefined sets of object attributes.
one of these is the set of attributes identfying uniquely the object
(primary key).
A naïve attempt to do the job:

class ObjectClass:
""" Test primary Key assignment """

if __name__ == "__main__":

ObjectClassInstantiated=ObjectClass()
ObjectClassInstantiated.AnAttribute='First PK Elem'
ObjectClassInstantiated.AnotherOne='Second PK Elem'
ObjectClassInstantiated.Identifier=[]
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnotherOne)
print ObjectClassInstantiated.Identifier
ObjectClassInstantiated.AnAttribute='First PK Elem Changed'
print ObjectClassInstantiated.Identifier

leads a wrong result
./test.py
['First PK Elem', 'Second PK Elem']
['First PK Elem', 'Second PK Elem']
--> wrong! It should write ['First PK Elem Changed', 'Second PK Elem']


i.e. the assgnment

ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)

assigns only the attribute value, not the reference.

so my question is:
is it still true that there is no possibilty to get directly object
references?
Is there a solution for the problem above ?
Thank you for any feedback and sorry for the long mail
....and the reference to perl :)

Regs,
Davide
 
F

Felipe Almeida Lessa

Em Sáb, 2006-03-25 às 21:33 -0800, DrConti escreveu:
[snip]
There was also a suggestion to write a real problem where referencing
is really needed.
I have one...:
[snap]

There are loads of discussions about the code you wrote... but... isn't
bad practice to put the same data in two places? Or am I missing
something?

Cheers,
 
D

DrConti

Felipe said:
Em Sáb, 2006-03-25 às 21:33 -0800, DrConti escreveu:
[snip]
There was also a suggestion to write a real problem where referencing
is really needed.
I have one...:
[snap]

There are loads of discussions about the code you wrote... but... isn't
bad practice to put the same data in two places? Or am I missing
something?

Cheers,
Hi Felipe, surely it's bad practice to put the same data in two places.
However I don't want to put the data in the identifier list, but just
the reference to the attributes.

My general problem is to find a way to define subsets of instance
attributes (for example the identifier), so that at later time I can
just iterate over the subset.
In the meantime I found a 90% solution to the problem through lambdas..
See now the code below: maybe you'll understand my point better.
Thanks and Regs,
Davide

class ObjectClass:
""" Test primary Key assignment
"""
def alias(self,key): return lambda: self.__dict__[key]
def __init__(self):
self.Identifier=[]

def getPK(self):
return [ GetPKValue() for GetPKValue in self.Identifier ]

if __name__ == "__main__":
ObjectClassInstantiated=ObjectClass()

ObjectClassInstantiated.AnAttribute='First PK Elem'
ObjectClassInstantiated.AnotherOne='Second PK Elem'
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.alias('AnAttribute'))
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.alias('AnotherOne'))
print ObjectClassInstantiated.getPK()
ObjectClassInstantiated.AnAttribute='First PK Elem Changed'
print ObjectClassInstantiated.getPK()
./test.py
['First PK Elem', 'Second PK Elem']
['First PK Elem Changed', 'Second PK Elem']
--> correct now!
 
D

Dennis Lee Bieber

I need a variable alias ( what in other languages you would call "a
pointer" (c) or "a reference" (perl))

Everything in Python is a "pointer" or "reference"...

But you aren't going to create the effect you want... Python does
not use the "post office box" metaphor where

A = C

means "look in the box [memory] with the address C, make a copy of the
contents, put the copy into the box with address A"

Instead, Python has what I refer to as "Post-It Notes"...

A = C

means "Take the Post-It Note with the name "A" written on it from
whatever box it is attached to -- create a new note if needed -- then
find the box that already has the Post-It with "C" on it, and stick the
"A" Post-It onto the same box. If the original "A" box has no other
Post-Its attached, destroy the box"

So...


ObjectClassInstantiated.AnAttribute='First PK Elem'

This attaches the Post-It "ObjectClassInstantiated.AnAttribute" to a
box containing "First PK Elem"
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)

This makes a Post-It "ObjectClassInstantiated.Identifier[0]" and
sticks it to the same box containing "First PK Elem"
ObjectClassInstantiated.AnAttribute='First PK Elem Changed'

This takes the "ObjectClassInstantiated.AnAttribute" Post-It away
from the box containing "First PK Elem" and sticks it on a box (newly
created) containing 'First PK Elem Changed'.
"ObjectClassInstantiated.Identifier[0]" is still attached to the box
with "First PK Elem".
--> wrong! It should write ['First PK Elem Changed', 'Second PK Elem']
No, CORRECT --- For PYTHON

Another thing -- Python strings are "immutable"; a string can not be
changed; you can only create a new string (somewhere else in memory) and
bind the variable name to the new string; this does not change any other
bindings to other names.
so my question is:
is it still true that there is no possibilty to get directly object
references?
alst = []
name1 = "First String"
name2 = "second string"
alst.append(name1)
alst.append(name2)
print id(name1), id(alst[0])
16027104 16027104
#SAME OBJECT
name1 = "modified?"
print id(name1), id(alst[0])
16055416 16027104
#"name1" is now a DIFFERENT OBJECT. alst[0] is still the original
Is there a solution for the problem above ?

What problem? It's normal Python? The really snide remark would be
"Change your mental viewpoint to think in Python"
alst = []
name1 = ["First String"]
name2 = ["second string"]
alst.append(name1)
alst.append(name2)
print id(name1), id(alst[0]) 11640880 11640880
name1[0] = "modified?"
print id(name1), id(alst[0]) 11640880 11640880
print alst[0][0], name1[0] modified? modified?
Note; instead of binding name1/name2 to strings, I've bound them to
single element lists containing strings. Then, I modify the content of
the list (which is mutable), rather than binding to a new object.
['modified?'] [['modified?'], ['second string']]

Of course, you have to remember to index into the list to actually
get the data...
name2[0] = alst
print name1, alst ['modified?'] [['modified?'], [[...]]]
print name2 [[['modified?'], [...]]]
 
M

Mitja Trampus

DrConti said:
class ObjectClass:
""" Test primary Key assignment """

if __name__ == "__main__":
ObjectClassInstantiated=ObjectClass()
ObjectClassInstantiated.AnAttribute='First PK Elem'
ObjectClassInstantiated.AnotherOne='Second PK Elem'
ObjectClassInstantiated.Identifier=[]
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnotherOne)
print ObjectClassInstantiated.Identifier
ObjectClassInstantiated.AnAttribute='First PK Elem Changed'
print ObjectClassInstantiated.Identifier

leads a wrong result
./test.py
['First PK Elem', 'Second PK Elem']
['First PK Elem', 'Second PK Elem']
--> wrong! It should write ['First PK Elem Changed', 'Second PK Elem']

i.e. the assgnment
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)
assigns only the attribute value, not the reference.

Nono, it assigns the reference alright. In python, EVERYTHING gets assigned only a
reference, .AnAttribute as well. So when you do .AnAttribute = 'Changed', you make it a
reference to a NEW string 'Changed', while .Identifier[0] keeps referencing the 'First PK'
string object.
Strings are an unfortunate example, since they're immutable - once you create a string
object, you cant't modify it any more. But if you had a more complex object, you could do
..AnAttribute.changeYourself(), and .Identifier[0] would change accordingly as well,
because .AnAttribute would keep pointing to the same object (albeit changed).

In your case, try .AnAttribute = ['First']; .Identifier[0] = .AnAttribute; .AnAttribute[0]
= 'First changed'; - this will work the way you want it to, because .AnAttribute doesn't
get rebound (only the content of the object (list) it's pointing to change, but it's still
the same object).
 
B

Bruno Desthuilliers

DrConti a écrit :
Dear Python developer community,
I'm quite new to Python, so perhaps my question is well known and the
answer too.

I need a variable alias ( what in other languages you would call "a
pointer" (c) or "a reference" (perl))

Well, that's the only kind of "variable"[1] in Python.

[1] the correct name in Python is 'binding', since it's about 'binding'
a reference to a name, not labelling an in-memory address and storing
data there.
I read some older mail articles and I found that the offcial position
about that was that variable referencing wasn't implemented because
it's considered bad style.
There was also a suggestion to write a real problem where referencing
is really needed.
I have one...:

You *think* you have one.
I'm trying to generate dynamically class methods which works on
predefined sets of object attributes.
one of these is the set of attributes identfying uniquely the object
(primary key).
A naïve attempt to do the job:

class ObjectClass:
""" Test primary Key assignment """

if __name__ == "__main__":

ObjectClassInstantiated=ObjectClass()
ObjectClassInstantiated.AnAttribute='First PK Elem'
ObjectClassInstantiated.AnotherOne='Second PK Elem'
ObjectClassInstantiated.Identifier=[]
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnotherOne)
print ObjectClassInstantiated.Identifier
ObjectClassInstantiated.AnAttribute='First PK Elem Changed'
print ObjectClassInstantiated.Identifier

leads a wrong result
./test.py

['First PK Elem', 'Second PK Elem']
['First PK Elem', 'Second PK Elem']
--> wrong! It should write ['First PK Elem Changed', 'Second PK Elem']

Nope, it's exactly what you asked for !-)
i.e. the assgnment

ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)

assigns only the attribute value, not the reference.

1/ it's not an assignement
2/ it does not store the attribute "value", it stores the reference to
the object the attribute is bound to. When you later rebind the
attribute, it only impact this binding - there's no reason it should
impact other bindings.

so my question is:
is it still true that there is no possibilty to get directly object
references?

But object references *are* what you have.
Is there a solution for the problem above ?

Yes : keep a reference to the attribute name, not to the value bound to
that name. There are many ways to do it, here's one:

ObjectClass.Identifier = property(
fget=lambda self: [self.AnAttribute, self.AnotherOne]
)

and here's another one:

ObjectClassInstantiated._identifier_parts = []
# note the use of strings, not symbols
ObjectClassInstantiated._identifier_parts.append("AnAttribute")
ObjectClassInstantiated._identifier_parts.append("AnotherOne")

ObjectClass.Identifier = property(
fget=lambda self: [getattr(self, name) \
for name in self._identifier_parts]
)

Thank you for any feedback

May I add some ? Your naming conventions are highly unpythonic. We
usually use CamelCase for classes names, and (in order of preference)
all_lower_with_underscores or mixedCaps for
variables/attributes/functions etc.

HTH
 
S

Steven D'Aprano

Dear Python developer community,
I'm quite new to Python, so perhaps my question is well known and the
answer too.

I need a variable alias ( what in other languages you would call "a
pointer" (c) or "a reference" (perl))

Others have given you reasons why you can't do this, or shouldn't do this.
In general, I agree with them -- change your algorithm so you don't
need indirect references.

But if you can't get away from it, here is another work-around that might
help:


class ObjectClass:
""" Test primary Key assignment """

if __name__ == "__main__":

ObjectClassInstantiated=ObjectClass()
ObjectClassInstantiated.AnAttribute='First PK Elem'
ObjectClassInstantiated.AnotherOne='Second PK Elem'
ObjectClassInstantiated.Identifier=[]
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnotherOne)
print ObjectClassInstantiated.Identifier
ObjectClassInstantiated.AnAttribute='First PK Elem Changed'
print ObjectClassInstantiated.Identifier


# helper class
class Indirect:
def __init__(self, value):
self.value = value
def mutate(self, newvalue):
self.value = newvalue
def __eq__(self, other):
return self.value == other
def __repr__(self):
return "-> %r" % self.value

instance = ObjectClass()
instance.attribute = Indirect('First PK Elem')
instance.another_attribute = Indirect('Second PK Elem')
instance.identifier = [instance.attribute, instance.another_attribute]

print instance.identifier
instance.attribute.mutate('First PK Elem Changed')
print instance.identifier

which prints

[-> 'First PK Elem', -> 'Second PK Elem']
[-> 'First PK Elem Changed', -> 'Second PK Elem']

as requested.
 
B

bruno at modulix

Steven said:
Others have given you reasons why you can't do this, or shouldn't do this.
In general, I agree with them -- change your algorithm so you don't
need indirect references.

But if you can't get away from it, here is another work-around that might
help:

(snip)

And another one, that mess less with attributes (but more with lookup
rules - use it at your own risks !-):

class CompoundAttribute(object):
def __init__(self, *names):
self._names = names
def __get__(self, obj, objtype):
if obj is None:
return self
return [getattr(obj, name) for name in self._names]
def __set__(self, obj, value):
raise TypeError, "object '%s' does not support assignement" % self

import types


class ObjectClass(object):
def __getattribute__(self, name):
v = object.__getattribute__(self, name)
if not isinstance(v, types.FunctionType) \
and hasattr(v, '__get__'):
return v.__get__(self, self.__class__)
return v

instance = ObjectClass()
instance.attribute = 'First PK Elem'
instance.another_attribute = 'Second PK Elem'
instance.identifier = CompoundAttribute('attribute', 'another_attribute')

NB : Sorry, not tested.
 
S

Scott David Daniels

DrConti said:
I need a variable alias ( what in other languages you would call "a
pointer" (c) or "a reference" (perl))
Or, you think you need it.
I read some older mail articles and I found that the offcial position
about that was that variable referencing wasn't implemented because
it's considered bad style.
Generally, yes. The line goes, roughly, "You've decided on a solution
and are twisting your problem to fit it."

There was also a suggestion to write a real problem where referencing
is really needed. I have one...:

I'm trying to generate dynamically class methods which works on
predefined sets of object attributes.
one of these is the set of attributes identfying uniquely the object
(primary key).

First, this is _not_ a "real problem"; this is a bunch of code. The
"real problem" request is to provide an actual use case, not some code
where you want to write what you want to write.
A naïve attempt to do the job:

class ObjectClass:
""" Test primary Key assignment """

if __name__ == "__main__":

ObjectClassInstantiated=ObjectClass()
ObjectClassInstantiated.AnAttribute='First PK Elem'
ObjectClassInstantiated.AnotherOne='Second PK Elem'
ObjectClassInstantiated.Identifier=[]
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectClassInstantiated.AnotherOne)
print ObjectClassInstantiated.Identifier
ObjectClassInstantiated.AnAttribute='First PK Elem Changed'
print ObjectClassInstantiated.Identifier

If you insist on this kind of approach, you could use a pair of
an object, and an attribute name as a "reference," and use getattr
and setattr to access the identified attribute. _But__ I emphasize
that you are thinking about your problem from the point of view
of a solution, not from the point of view of the problem.

You'd probably like this:

class Example(object):
""" Test primary Key assignment """

def __init__(self, one, two, other):
self.one = one
self.two = two
self.other = other

def __repr__(self):
return '%s(%r, %r, %r)' % (
type(self).__name__, self.one, self.two, self.other)


if __name__ == "__main__":
eg = Example(3.1415, 3+4j, 'pi')
ref_attr = eg, 'one'
ref_other = eg, 'other'
print eg, getattr(*ref_attr), getattr(*ref_other)
eg.one = 'First PK Elem'
print eg, getattr(*ref_attr), getattr(*ref_other)
setattr(*ref_other + (u'Strangely',))
print eg, getattr(*ref_attr), getattr(*ref_other)

But you might consider this:

class Another(Example):
""" Test primary Key assignment """
key = ('one', 'two')


def getkey(v):
return [getattr(v, part) for part in v.key]

if __name__ == "__main__":
eg2 = Another(3.1415, 3+4j, 'pi')
print eg2, getkey(eg2)
eg2.one = 'First PK Elem'
print eg2, getkey(eg2)
setattr(eg2, 'two', u'Strangely')
print eg2, getkey(eg2)
 
D

DrConti

Hi Bruno, hi folks!
thank you very much for your advices.
I didn't know about the property function.
I learned also quite a lot now about "references".
Ok everything is a reference but you can't get a reference of a
reference...

I saw a lot of variations on how to solve this problem, but I find
actually that the "property approach" is the most natural of all.
Basically the idea there is that you build up this list of class
attributes not by storing a reference
to a class attribute (which seem to be impossible), but you just store
on each element of the list one method (pardon a reference to..) to get
the associated class attribute.

Sorry for the UnPythonity. I used to be a CamelRider.
But not very longtime ago I left the Camel in the Desert, because I met
the Snake....

Regs,
Davide.
 
B

bruno at modulix

DrConti said:
Hi Bruno, hi folks!
thank you very much for your advices.
I didn't know about the property function.
I learned also quite a lot now about "references".
Ok everything is a reference but you can't get a reference of a
reference...

I saw a lot of variations on how to solve this problem, but I find
actually that the "property approach" is the most natural of all.

So I need to add a little correction to the code snippet (sorry, got
confused by your namings - ie 'ObjectClass' - and some recent
exploration I did about per-instance descriptors) : Actually, using a
property as an *instance* attribute won't work - unless the class
redefine __getattribute__ this way:

class ObjectClass(object):
def __getattribute__(self, name):
v = object.__getattribute__(self, name)
if not isinstance(v, types.FunctionType) \
and hasattr(v, '__get__'):
return v.__get__(self, self.__class__)
return v

Basically the idea there is that you build up this list of class
attributes

These are not *class* attributes, but *instance* attributes.

I think you should really take some time to learn more about Python's
object model, attribute lookup rules, descriptors and metaclasses.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,120
Latest member
ShelaWalli
Top