OO issues in python

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ali El Dada

    OO issues in python

    hi all:

    in python, when a class, say Father, has a member that itself is an
    instance of another class, say Child, an instance of Father actually
    only has a reference to a Child, not the Child object itself, right?

    because i know that in eiffel they give the programmer the 2 options,
    the second being implemented with an additional keyword (expanded) so as
    the eiffel documentation says,

    "Consider the example of a class covering the notion of car. Many cars
    share the same originating_pla nt , but an engine belongs to just one
    car. References represent the modeling relation "knows about";
    subobjects, as permitted by expanded types, represent the relation "has
    part", also known as aggregation. The key difference is that sharing is
    possible in the former case but not in the latter"

    the reason why i'm asking is that i want my Child() instance to know
    things about the parent without having to explicitly pass them as
    arguments. this is not working :(

    eg code that doesn't work:

    class Father:

    def __init__(self):
    self.a = 'foo'
    self.son = Child()

    class Child:

    def __init__(self):
    print f.a


    f = Father()

    thanks for any help..

    Cheers,
    Ali Dada

  • Lutz Horn

    #2
    Re: OO issues in python

    Hi,

    * Ali El Dada <eldada@mdstud. chalmers.se> [17 Dez 2003]:[color=blue]
    > "Consider the example of a class covering the notion of car. Many
    > cars share the same originating_pla nt , but an engine belongs to
    > just one car. References represent the modeling relation "knows
    > about"; subobjects, as permitted by expanded types, represent the
    > relation "has part", also known as aggregation. The key difference
    > is that sharing is possible in the former case but not in the
    > latter"[/color]

    The word "sharing" in the description of a reference means that many
    instances of car could hold a reference to the same instance of
    engine. Many cars would know about and share the same engine (this is
    some stupid example :-).

    Aggregation means that one and only one car has a given instance of
    an engine. Another car must have a different engine.
    [color=blue]
    > the reason why i'm asking is that i want my Child() instance to
    > know things about the parent without having to explicitly pass
    > them as arguments. this is not working :([/color]

    This has nothing to do with the difference between referencing and
    aggregating. A Child doesn't know a thing about it's Father in both
    cases.

    For the Child to know about the Father you have to pass the Child a
    reference to the Father.
    [color=blue]
    > eg code that doesn't work:
    >
    > class Father:
    >
    > def __init__(self):
    > self.a = 'foo'
    > self.son = Child()
    >
    > class Child:
    >
    > def __init__(self):
    > print f.a[/color]

    What is f?
    [color=blue]
    > f = Father()[/color]

    This instance of Father is out of scope for any method of a Child
    instance.

    Regards
    Lutz
    --
    no sig

    Comment

    • Bruno Desthuilliers

      #3
      Re: OO issues in python

      Ali El Dada wrote:[color=blue]
      > hi all:
      >
      > in python, when a class, say Father, has a member that itself is an
      > instance of another class, say Child, an instance of Father actually
      > only has a reference to a Child, not the Child object itself, right?[/color]

      I'm not sure I get the point. With Python, you only have symbols that
      are bounds to objects.
      [color=blue]
      > because i know that in eiffel they give the programmer the 2 options,
      > the second being implemented with an additional keyword (expanded) so as
      > the eiffel documentation says,
      >
      > "Consider the example of a class covering the notion of car. Many cars
      > share the same originating_pla nt , but an engine belongs to just one
      > car. References represent the modeling relation "knows about";
      > subobjects, as permitted by expanded types, represent the relation "has
      > part", also known as aggregation. The key difference is that sharing is
      > possible in the former case but not in the latter"[/color]

      No such thing in Python. But it comes down to :
      1/ an object A is 'shared' by many others B* (composition) :
      you instanciate A, and pass it to each B that needs to 'know about' it.

      2/ an object A is 'part of' an object B (aggregation) :
      B instanciate A, and no one else keeps a reference to A.

      [color=blue]
      > the reason why i'm asking is that i want my Child() instance to know
      > things about the parent without having to explicitly pass them as
      > arguments.[/color]

      This seems quite a different problem. AFAICT, the Eiffel mechanism you
      mention don't let 'part' objects know anything about the object that
      'own' them (I may be wrong since I don't know Eiffel that much, but...).
      [color=blue]
      > this is not working :([/color]

      I can't see how it could work. A object instance can only know what you
      let it know, so unless you pass it a ref to another object, it can't
      know nothing about it.
      [color=blue]
      > eg code that doesn't work:
      >
      > class Father:
      >
      > def __init__(self):
      > self.a = 'foo'
      > self.son = Child()
      >
      > class Child:
      >
      > def __init__(self):
      > print f.a[/color]
      where is this 'f' coming from ?-)
      [color=blue]
      >
      > f = Father()
      >[/color]
      How would you expect the Child *class* to know anything about a symbol
      that is yet unbound ?

      You have two options :

      1/
      class Father:
      def __init__(self):
      self.a = a
      self.son = Child(self)

      def doIt(self):
      self.son.someth ingElse()


      class Child:
      def __init__(self, father):
      self.father = father
      print self.father.a

      def somethingElse(s elf):
      print self.father.a


      2/
      class Father:
      def __init__(self):
      self.a = a
      self.son = Child(self)

      def doIt(self):
      self.son.someth ingElse(self)


      class Child:
      def __init__(self, father):
      print father.a

      def somethingElse(s elf, father):
      print father.a


      Note that
      - with the first solution, you create a circular reference between
      Father and Child instances - but Python now has a real GC that handle
      such situations, so this may not be a problem.

      - with the second solution, you can pass any other Father-like object to
      a Child instance, which may or may not be a problem.

      Now there is no "Good" or "Bad" solution, it depends on the problem at hand.

      HTH
      Bruno

      Comment

      • Albert Hofkamp

        #4
        Re: OO issues in python

        On Wed, 17 Dec 2003 11:23:33 +0100, Ali El Dada <eldada@mdstud. chalmers.se> wrote:[color=blue]
        > in python, when a class, say Father, has a member that itself is an
        > instance of another class, say Child, an instance of Father actually
        > only has a reference to a Child, not the Child object itself, right?[/color]

        Correct, although I don't rally see why this is important.
        [color=blue]
        > because i know that in eiffel they give the programmer the 2 options,
        > the second being implemented with an additional keyword (expanded) so as
        > the eiffel documentation says,
        >
        > "Consider the example of a class covering the notion of car. Many cars
        > share the same originating_pla nt , but an engine belongs to just one[/color]

        You mean inheritance here, as in

        class Father(Child):
        ...

        ?
        [color=blue]
        > car. References represent the modeling relation "knows about";
        > subobjects, as permitted by expanded types, represent the relation "has
        > part", also known as aggregation. The key difference is that sharing is
        > possible in the former case but not in the latter"[/color]

        Sharing is normally in one direction only, ie from Father to Child,
        afaik in both cases (both member-of and inheritance).
        Normally, one would write Child without being aware of Father, that is,
        Child should be written as a stand-alone, so it may be used in arbitrary
        contexts, such as

        class Mother(Child):
        ..
        [color=blue]
        > the reason why i'm asking is that i want my Child() instance to know
        > things about the parent without having to explicitly pass them as
        > arguments. this is not working :([/color]

        You are trying to do something that is contradictionar y to the OO idea.
        Luckily, that does not mean it is impossible to do.

        If the parent and the child class need to share data, you either put the
        data in the sub-class (ie Child), or you create a new class that holds
        the data where both the parent and the child have access to.

        Imho the first solution is preferrable because of a well-defined
        ownership of the data.


        Albert
        --
        Unlike popular belief, the .doc format is not an open publically available format.

        Comment

        • Ali El Dada

          #5
          Re: OO issues in python

          ok thanks, i understood my mistake, now to the solution:


          Albert Hofkamp wrote:
          [color=blue]
          >
          > If the parent and the child class need to share data, you either put the
          > data in the sub-class (ie Child), or you create a new class that holds
          > the data where both the parent and the child have access to.
          >[/color]

          well the first solution is not feasible with me because i may have more
          classes and subclasses that may need this information (it is like a
          dictionary that has some global information, e.g. about the environment)

          so do you advise me to take the second solution, creating a class called
          Global that any other class can access?? as in: (not tested)

          class Global:
          user_home = os.environ['HOME']
          my_app_data = 'C:\\Program Files\\MyApp'

          class AnyClass:
          self.user_home = Global.user_hom e

          Comment

          • Lutz Horn

            #6
            Re: OO issues in python

            Hi,

            * Ali El Dada <eldada@mdstud. chalmers.se> [17 Dez 2003]:[color=blue]
            > Albert Hofkamp wrote:[color=green]
            >> If the parent and the child class need to share data, you either
            >> put the data in the sub-class (ie Child), or you create a new
            >> class that holds the data where both the parent and the child
            >> have access to.[/color]
            >
            > well the first solution is not feasible with me because i may have
            > more classes and subclasses that may need this information (it is
            > like a dictionary that has some global information, e.g. about the
            > environment)[/color]

            What's the problem with passing the context to every instance of a
            subclass? It's only a parameter in a constructor or the call of a
            method like setContext().
            [color=blue]
            > so do you advise me to take the second solution, creating a class
            > called Global that any other class can access?? as in: (not
            > tested)
            >
            > class Global:
            > user_home = os.environ['HOME']
            > my_app_data = 'C:\\Program Files\\MyApp'
            >
            > class AnyClass:
            > self.user_home = Global.user_hom e[/color]

            No, don't use global data.

            Lutz
            --
            no sig

            Comment

            • Ali El Dada

              #7
              Re: OO issues in python

              ok that settles everything.. thanks a million!!!


              Regards,
              Ali Dada


              Lutz Horn wrote:[color=blue]
              > Hi,
              >
              > * Ali El Dada <eldada@mdstud. chalmers.se> [17 Dez 2003]:
              >[color=green]
              >>Albert Hofkamp wrote:
              >>[color=darkred]
              >>>If the parent and the child class need to share data, you either
              >>>put the data in the sub-class (ie Child), or you create a new
              >>>class that holds the data where both the parent and the child
              >>>have access to.[/color]
              >>
              >>well the first solution is not feasible with me because i may have
              >>more classes and subclasses that may need this information (it is
              >>like a dictionary that has some global information, e.g. about the
              >>environment )[/color]
              >
              >
              > What's the problem with passing the context to every instance of a
              > subclass? It's only a parameter in a constructor or the call of a
              > method like setContext().
              >
              >[color=green]
              >>so do you advise me to take the second solution, creating a class
              >>called Global that any other class can access?? as in: (not
              >>tested)
              >>
              >>class Global:
              >> user_home = os.environ['HOME']
              >> my_app_data = 'C:\\Program Files\\MyApp'
              >>
              >>class AnyClass:
              >> self.user_home = Global.user_hom e[/color]
              >
              >
              > No, don't use global data.
              >
              > Lutz[/color]

              Comment

              • Terry Reedy

                #8
                Re: OO issues in python


                "Ali El Dada" <eldada@mdstud. chalmers.se> wrote in
                message news:brpar5$c47 $1@eol.dd.chalm ers.se...[color=blue]
                > in python, when a class, say Father, has a[/color]
                member that itself is an[color=blue]
                > instance of another class, say Child, an[/color]
                instance of Father actually[color=blue]
                > only has a reference to a Child, not the Child[/color]
                object itself, right?

                Good question. As you defined the difference by
                quoting from Eiffel, yes. The association
                relating names and collection slots to objects is
                many to one. A given object can be associated
                with (referenced by) multiple names, lists, dicts,
                and instances. This is essential to Python's
                operation. If you want to restrict the
                association to be one to one (as in engine belongs
                to only one car), you must exert the discipline
                yourself. You can facilitate this by making the
                restricted class private to a module or another
                class. I have never heard of this being a
                problem.
                [color=blue]
                > eg code that doesn't work:
                >[/color]
                class Father:
                def __init__(self):
                self.a = 'foo'
                self.son = Child()

                class Child:
                def __init__(self):
                print f.a

                f = Father()

                Put on your Python interpreter hat and try to
                execute this. Father calls Father.__init__ calls
                Child calls Child.__init__ tries to access object
                named f, but there is no such object because the
                calls have not returned and hence the binding of
                global f to Father instance has not yet occurred
                and hence you get a NameError.
                [color=blue][color=green][color=darkred]
                >>> f = Father()[/color][/color][/color]
                Traceback (most recent call last):
                File "<stdin>", line 1, in ?
                File "<stdin>", line 4, in __init__
                File "<stdin>", line 3, in __init__
                NameError: global name 'f' is not defined

                (Please, when you post code that 'does not work',
                cut and paste the error traceback as above.)

                If you want to create a circular reference between
                Father and Child, pass the Father instance to the
                Child initialization.

                class Father:
                def __init__(self):
                self.a = 'foo'
                self.son = Child(self)

                class Child:
                def __init__(self, father):
                self.father = father
                print father.a
                [color=blue][color=green][color=darkred]
                >>> f = Father()[/color][/color][/color]
                foo

                Terry J. Reedy


                Comment

                • John Landahl

                  #9
                  Re: OO issues in python

                  Ali El Dada <eldada@mdstud. chalmers.se> wrote in message news:<brph4c$er 0$1@eol.dd.chal mers.se>...
                  [color=blue]
                  > so do you advise me to take the second solution, creating a class called
                  > Global that any other class can access?? as in: (not tested)
                  >
                  > class Global:
                  > user_home = os.environ['HOME']
                  > my_app_data = 'C:\\Program Files\\MyApp'
                  >
                  > class AnyClass:
                  > self.user_home = Global.user_hom e[/color]

                  Take a look at PEAK, the Python Enterprise Application Kit
                  (http://peak.telecommunity.com/). It has advanced configuration and
                  binding capabilities that make this sort of thing incredibly simple
                  (and which provide far more power and flexibility), without needing to
                  resort to singletons like your Global class.

                  Using PEAK your AnyClass might look like this:

                  from peak.api import binding, PropertyName
                  class AnyClass(bindin g.Component):
                  user_home = binding.Obtain( PropertyName('e nviron.HOME'))
                  app_data = binding.Obtain( PropertyName('m yapp.data'))

                  binding.Obtain allows you to locate and "bind to" an object that's
                  been created elsewhere in the program. Objects are located through
                  "configurat ion keys" -- in this case dotted "property names" are used,
                  though there are other choices which provide even more flexibility.
                  Properties provide a simple way to organize data hierarchically (e.g.
                  'myapp.foo.bar. whatever') and which have a direct tie-in to external
                  ..ini config files. "environ.*" provides a simple way to lookup
                  environment variables, and "myapp.data " could be specified in a config
                  file like so:

                  [myapp]
                  data = 'C:\\Program Files\\MyApp'

                  There's a great introductory tutorial on the PEAK DevCenter wiki:



                  It walks you through creating simple applications with these features,
                  and moves on to more advanced PEAK features that you might also find
                  useful.

                  Comment

                  Working...