By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,650 Members | 1,858 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,650 IT Pros & Developers. It's quick & easy.

object references

P: n/a
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 nave 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(ObjectCl assInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectCl assInstantiated.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(ObjectCl assInstantiated.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

Mar 26 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
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,

--
Felipe.

Mar 26 '06 #2

P: n/a
Felipe Almeida Lessa schrieb:
Em Sb, 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,

--
Felipe.

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(ObjectCl assInstantiated.alias('AnAttribute'))
ObjectClassInstantiated.Identifier.append(ObjectCl assInstantiated.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!

Mar 26 '06 #3

P: n/a
DrConti wrote:
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(ObjectCl assInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectCl assInstantiated.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(ObjectCl assInstantiated.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).
Mar 26 '06 #4

P: n/a
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 nave 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(ObjectCl assInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectCl assInstantiated.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(ObjectCl assInstantiated.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
Mar 26 '06 #5

P: n/a
On Sat, 25 Mar 2006 21:33:24 -0800, DrConti wrote:
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(ObjectCl assInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectCl assInstantiated.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.
--
Steven.

Mar 27 '06 #6

P: n/a
Steven D'Aprano wrote:
On Sat, 25 Mar 2006 21:33:24 -0800, DrConti wrote:

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:


(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.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Mar 27 '06 #7

P: n/a
DrConti wrote:
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 nave 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(ObjectCl assInstantiated.AnAttribute)
ObjectClassInstantiated.Identifier.append(ObjectCl assInstantiated.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)
--
-Scott David Daniels
sc***********@acm.org
Mar 27 '06 #8

P: n/a
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.

Mar 27 '06 #9

P: n/a
DrConti wrote:
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.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Mar 28 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.