object references

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • DrConti

    #1

    object references

    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__":

    ObjectClassInst antiated=Object Class()
    ObjectClassInst antiated.AnAttr ibute='First PK Elem'
    ObjectClassInst antiated.Anothe rOne='Second PK Elem'
    ObjectClassInst antiated.Identi fier=[]
    ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnAttribu te)
    ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnotherOn e)
    print ObjectClassInst antiated.Identi fier
    ObjectClassInst antiated.AnAttr ibute='First PK Elem Changed'
    print ObjectClassInst antiated.Identi fier

    leads a wrong result[color=blue]
    >./test.py[/color]
    ['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

    ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnAttribu te)

    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

  • Felipe Almeida Lessa

    #2
    Re: object references

    Em Sáb, 2006-03-25 às 21:33 -0800, DrConti escreveu:
    [snip][color=blue]
    > There was also a suggestion to write a real problem where referencing
    > is really needed.
    > I have one...:[/color]
    [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.

    Comment

    • DrConti

      #3
      Re: object references

      Felipe Almeida Lessa schrieb:
      [color=blue]
      > Em Sáb, 2006-03-25 às 21:33 -0800, DrConti escreveu:
      > [snip][color=green]
      > > There was also a suggestion to write a real problem where referencing
      > > is really needed.
      > > I have one...:[/color]
      > [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.[/color]
      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__":
      ObjectClassInst antiated=Object Class()

      ObjectClassInst antiated.AnAttr ibute='First PK Elem'
      ObjectClassInst antiated.Anothe rOne='Second PK Elem'
      ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.alias('An Attribute'))
      ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.alias('An otherOne'))
      print ObjectClassInst antiated.getPK( )
      ObjectClassInst antiated.AnAttr ibute='First PK Elem Changed'
      print ObjectClassInst antiated.getPK( )
      [color=blue]
      >./test.py[/color]
      ['First PK Elem', 'Second PK Elem']
      ['First PK Elem Changed', 'Second PK Elem']
      --> correct now!

      Comment

      • Mitja Trampus

        #4
        Re: object references

        DrConti wrote:[color=blue]
        > class ObjectClass:
        > """ Test primary Key assignment """
        >
        > if __name__ == "__main__":
        > ObjectClassInst antiated=Object Class()
        > ObjectClassInst antiated.AnAttr ibute='First PK Elem'
        > ObjectClassInst antiated.Anothe rOne='Second PK Elem'
        > ObjectClassInst antiated.Identi fier=[]
        > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnAttribu te)
        > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnotherOn e)
        > print ObjectClassInst antiated.Identi fier
        > ObjectClassInst antiated.AnAttr ibute='First PK Elem Changed'
        > print ObjectClassInst antiated.Identi fier
        >
        > leads a wrong result[color=green]
        >> ./test.py[/color]
        > ['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
        > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnAttribu te)
        > assigns only the attribute value, not the reference.[/color]

        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.c hangeYourself() , 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).

        Comment

        • Bruno Desthuilliers

          #5
          Re: object references

          DrConti a écrit :[color=blue]
          > 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))[/color]

          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.
          [color=blue]
          > 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...:[/color]

          You *think* you have one.
          [color=blue]
          > 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__":
          >
          > ObjectClassInst antiated=Object Class()
          > ObjectClassInst antiated.AnAttr ibute='First PK Elem'
          > ObjectClassInst antiated.Anothe rOne='Second PK Elem'
          > ObjectClassInst antiated.Identi fier=[]
          > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnAttribu te)
          > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnotherOn e)
          > print ObjectClassInst antiated.Identi fier
          > ObjectClassInst antiated.AnAttr ibute='First PK Elem Changed'
          > print ObjectClassInst antiated.Identi fier
          >
          > leads a wrong result
          >[color=green]
          >>./test.py[/color]
          >
          > ['First PK Elem', 'Second PK Elem']
          > ['First PK Elem', 'Second PK Elem']
          > --> wrong! It should write ['First PK Elem Changed', 'Second PK Elem'][/color]

          Nope, it's exactly what you asked for !-)
          [color=blue]
          >
          > i.e. the assgnment
          >
          > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnAttribu te)
          >
          > assigns only the attribute value, not the reference.[/color]

          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.

          [color=blue]
          > so my question is:
          > is it still true that there is no possibilty to get directly object
          > references?[/color]

          But object references *are* what you have.
          [color=blue]
          > Is there a solution for the problem above ?[/color]

          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.Ide ntifier = property(
          fget=lambda self: [self.AnAttribut e, self.AnotherOne]
          )

          and here's another one:

          ObjectClassInst antiated._ident ifier_parts = []
          # note the use of strings, not symbols
          ObjectClassInst antiated._ident ifier_parts.app end("AnAttribut e")
          ObjectClassInst antiated._ident ifier_parts.app end("AnotherOne ")

          ObjectClass.Ide ntifier = property(
          fget=lambda self: [getattr(self, name) \
          for name in self._identifie r_parts]
          )

          [color=blue]
          > Thank you for any feedback[/color]

          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

          Comment

          • Steven D'Aprano

            #6
            Re: object references

            On Sat, 25 Mar 2006 21:33:24 -0800, DrConti wrote:
            [color=blue]
            > 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))[/color]

            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:


            [color=blue]
            > class ObjectClass:
            > """ Test primary Key assignment """
            >
            > if __name__ == "__main__":
            >
            > ObjectClassInst antiated=Object Class()
            > ObjectClassInst antiated.AnAttr ibute='First PK Elem'
            > ObjectClassInst antiated.Anothe rOne='Second PK Elem'
            > ObjectClassInst antiated.Identi fier=[]
            > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnAttribu te)
            > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnotherOn e)
            > print ObjectClassInst antiated.Identi fier
            > ObjectClassInst antiated.AnAttr ibute='First PK Elem Changed'
            > print ObjectClassInst antiated.Identi fier[/color]


            # 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.attrib ute = Indirect('First PK Elem')
            instance.anothe r_attribute = Indirect('Secon d PK Elem')
            instance.identi fier = [instance.attrib ute, instance.anothe r_attribute]

            print instance.identi fier
            instance.attrib ute.mutate('Fir st PK Elem Changed')
            print instance.identi fier

            which prints

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

            as requested.


            --
            Steven.

            Comment

            • bruno at modulix

              #7
              Re: object references

              Steven D'Aprano wrote:[color=blue]
              > On Sat, 25 Mar 2006 21:33:24 -0800, DrConti wrote:
              >
              >[color=green]
              >>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))[/color]
              >
              >
              > 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:[/color]

              (snip)

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

              class CompoundAttribu te(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(obj ect):
              def __getattribute_ _(self, name):
              v = object.__getatt ribute__(self, name)
              if not isinstance(v, types.FunctionT ype) \
              and hasattr(v, '__get__'):
              return v.__get__(self, self.__class__)
              return v

              [color=blue]
              > instance = ObjectClass()[/color]
              instance.attrib ute = 'First PK Elem'
              instance.anothe r_attribute = 'Second PK Elem'
              instance.identi fier = CompoundAttribu te('attribute', 'another_attrib ute')

              NB : Sorry, not tested.


              --
              bruno desthuilliers
              python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
              p in 'onurb@xiludom. gro'.split('@')])"

              Comment

              • Scott David Daniels

                #8
                Re: object references

                DrConti wrote:[color=blue]
                > I need a variable alias ( what in other languages you would call "a
                > pointer" (c) or "a reference" (perl))[/color]
                Or, you think you need it.
                [color=blue]
                > 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.[/color]
                Generally, yes. The line goes, roughly, "You've decided on a solution
                and are twisting your problem to fit it."

                [color=blue]
                > 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).[/color]

                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.
                [color=blue]
                > A naïve attempt to do the job:
                >
                > class ObjectClass:
                > """ Test primary Key assignment """
                >
                > if __name__ == "__main__":
                >
                > ObjectClassInst antiated=Object Class()
                > ObjectClassInst antiated.AnAttr ibute='First PK Elem'
                > ObjectClassInst antiated.Anothe rOne='Second PK Elem'
                > ObjectClassInst antiated.Identi fier=[]
                > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnAttribu te)
                > ObjectClassInst antiated.Identi fier.append(Obj ectClassInstant iated.AnotherOn e)
                > print ObjectClassInst antiated.Identi fier
                > ObjectClassInst antiated.AnAttr ibute='First PK Elem Changed'
                > print ObjectClassInst antiated.Identi fier[/color]

                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).__na me__, 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_at tr), getattr(*ref_ot her)
                eg.one = 'First PK Elem'
                print eg, getattr(*ref_at tr), getattr(*ref_ot her)
                setattr(*ref_ot her + (u'Strangely',) )
                print eg, getattr(*ref_at tr), getattr(*ref_ot her)

                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
                scott.daniels@a cm.org

                Comment

                • DrConti

                  #9
                  Re: object references

                  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.

                  Comment

                  • bruno at modulix

                    #10
                    Re: object references

                    DrConti wrote:[color=blue]
                    > 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.[/color]

                    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(obj ect):
                    def __getattribute_ _(self, name):
                    v = object.__getatt ribute__(self, name)
                    if not isinstance(v, types.FunctionT ype) \
                    and hasattr(v, '__get__'):
                    return v.__get__(self, self.__class__)
                    return v

                    [color=blue]
                    > Basically the idea there is that you build up this list of class
                    > attributes[/color]

                    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 'onurb@xiludom. gro'.split('@')])"

                    Comment

                    Working...