using names before they're defined

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

    #16
    Re: using names before they're defined

    Dave,

    Python properties allow you to get rid of methods like c.getAttr(),
    c.setAttr(v), c.delAttr() and replace them with simple constructs like
    c.attr, c.attr=v and del c.attr.

    If you have been using Java or C++ you know that as soon as you code
    your class you have to start filling in the get() set()
    delete()/reset() methods for each attribute. Some IDE tools like
    Netbeans will to it for you with code refactoring and such. But for 10
    attributes you will end up having another 20 or so
    accessors/setters/and erase methods.

    In Python not too long ago they introduced properties. With properties
    you just access you attributes as attributes c.attr and c.attr=value if
    you don't need to do anything special during getting and setting. Then
    you can safely publish your API for everyone to use. If one day you
    find a off-by-1 bug and you need to change one of the attributes when
    it is accessed or set, you use properties. You create a method like
    _get_attr(self) or _set_attr(self, v) in your class and at the end of
    the class definition you write:
    attr=property(_ get_attr, _set_attr). From then on, when someone
    accesses the attribute of your class c.attr the function _get_attr()
    will be automatically called, in there you can do whatever you need and
    return the value.

    Check out this page:

    Look further down in the page for "properties ".

    Also take a look at "Python Is Not Java" article, it was interesting
    for me to read. Properties getters and setters are mentioned there too
    under the "getter and setters are Evil!" section ;) Here is the link:


    Nick V.

    davehowey@f2s.c om wrote:
    Even if you need to do something during attachment of components it is
    more Pythonic to use properties. So you will write a method in your
    class name something like _set_up(self,up stream_obj) an _get_up(self).
    And then at the end of your class put up=property(_ge t_up, _set_up).
    You can still use the compr.up=... format.
    >
    sorry, I don't quite follow. what are properties?
    >
    Also, you might want to re-think your OO design. It seem that all of
    your components do a lot of things in common already. For one they all
    are connected to other components like themselves, they also propably
    will have method to do some computing, perhaps send or receive stuff
    from other components, or they all will implement somekind of an event
    model. In that case you could create a generic component class and
    sublass the specific implementations from it.
    >
    yes, I already do this - I have a component class and then the other
    components inherit from it.
    >
    Dave

    Comment

    • Steve Holden

      #17
      Re: using names before they're defined

      jordan.nick@gma il.com wrote:
      Steve Holden wrote:
      >
      >>davehowey@f2s .com wrote:
      >>
      >>>I have a problem. I'm writing a simulation program with a number of
      >>>mechanical components represented as objects. When I create instances
      >>>of objects, I need to reference (link) each object to the objects
      >>>upstream and downstream of it, i.e.
      >>>
      >>>supply = supply()
      >>>compressor = compressor(down stream=combusto r, upstream=supply )
      >>>combuster = combuster(downs tream=turbine, upstream=compre ssor)
      >>>etc.
      >>>
      >>>the problem with this is that I reference 'combustor' before is it
      >>>created. If I swap the 2nd and 3rd lines I get the same problem
      >>>(compresso r is referenced before creation).
      >>>
      >>>
      >>>aargh!!! any ideas on getting around this?
      >>>
      >>
      >>Yes. You are building a generic data structure, so you shouldn't really
      >>be trying to store individual objects in variables like that. You need a
      >>data structure that's appropriate to your problem.
      >>
      >>For example, you could consider storing them in a list, so you have
      >>
      >>components = [supply(), compressor(), combuster()]
      >>
      >>Then components[n] is upstream of components[n-1] and downstream of
      >>components[n+1].
      >
      >
      Unfortunately, if he wanted to make the topology more complicated, for
      instance having two components downstream, it would be much more
      cumbersome to inherit the list object and implement this.
      >
      I quite agree. That was why I began with "for example".
      >
      >>In short, your thinking about data representation might need to become a
      >>little more sophisticated.
      >
      >
      That sounds a little arrogant. sorry!
      >
      Hmm, maybe it does, in which case I apologise retrospectively . But all
      the more appropriate suggestions have definitely been pointing that way.

      Circuit design is a complex problem. I was merely trying to indicate
      that the naive approach was unlikely to succeed. Sure enough, a few
      posts later the OP admitted that there needed to be sub-chains for
      sub-circuits, and so on.

      regards
      Steve
      --
      Steve Holden +44 150 684 7255 +1 800 494 3119
      Holden Web LLC/Ltd http://www.holdenweb.com
      Skype: holdenweb http://holdenweb.blogspot.com
      Recent Ramblings http://del.icio.us/steve.holden

      Comment

      • Iain King

        #18
        Re: using names before they're defined


        davehowey@f2s.c om wrote:
        Iain, thanks - very helpful.
        >
        Really I'm trying to write a simulation program that goes through a
        number of objects that are linked to one another and does calculations
        at each object. The calculations might be backwards or fowards (i.e.
        starting at the supply or demand ends of the system and then working
        through the objects). And also, I might have multiple objects linked to
        a single object (upstream or downstream) - e.g. compressor -- multiple
        combusters - turbine
        >
        I like your idea of using something like a setStreams method to
        establish the linking. The streams do reflect each other, although
        having many-to-one and vice versa will complicate that. I have not
        quite got my head around having multiple links. In C++ I would be
        thinking about something like a linked-list but I'm not sure that's the
        right approach here.
        >
        Dave
        You don't need linked-lists : python has a list type built in.
        Example:

        class Component():

        upstream = []
        downstream = []

        def addUpstream(sel f, c):
        self.upstream.a ppend(c)
        if not self in c.downstream:
        c.addDownstream (self)

        def addDownstream(s elf, c):
        self.downstream .append(c)
        if not self in c.upstream:
        c.addUpstream(s elf)

        def remUpstream(sel f, c):
        c.downstream.re move(self)
        self.upstream.r emove(c)

        def remDownstream(s elf, c):
        c.upstream.remo ve(self)
        self.downstream .remove(c)

        def cascadeDownTest (self):
        print self
        # this could run forever if you connect components in a circle:
        for c in self.downstream :
        c.cascadeDownTe st()

        Iain

        Comment

        • davehowey@f2s.com

          #19
          Re: using names before they're defined

          Paddy,

          thanks for your mail.
          In Digital electronics we have what are called netlists, (and also
          component lists)
          yes, years back I did a 3rd year project on a 'logic simulator' which
          used the kind of thing you are talking about. I think spice does as
          well. Fortunately my problem is a little simpler, phew. [by the way, as
          an aside, check out modelia/dymola for some really powerful simulation
          stuff http://www.dynasim.se/ - it uses powerful symoblic algebra
          algorithms to derive system equations and the solve them numerically]
          With a bit more effort you can create component and link factories
          that will name instances with the variable they are assigned to
          without having to put that information in twice.
          sorry - could you explain a bit more? sounds interesting and also
          brings me onto another question that has been bugging me, which is, if
          I want to create components (as object instances) at run time (rather
          than through a python code imported in), how do I do this? i.e. if I
          hardcoded something like
          turbine1 = turbine(...)
          then python knows that turbine1 is a turbine. but if I had say some
          kind of user interface and I want to create turbine1 (or suchlike) on
          the fly, how do I actually do that? how do I create objects after run
          time?

          Dave

          Comment

          • Bruno Desthuilliers

            #20
            Re: using names before they're defined

            davehowey@f2s.c om wrote:
            (snip)
            brings me onto another question that has been bugging me, which is, if
            I want to create components (as object instances) at run time (rather
            than through a python code imported in), how do I do this? i.e. if I
            hardcoded something like
            turbine1 = turbine(...)
            then python knows that turbine1 is a turbine. but if I had say some
            kind of user interface and I want to create turbine1 (or suchlike) on
            the fly, how do I actually do that? how do I create objects after run
            time?
            Q&D possible solution, no error handling, etc
            ....just so you get an idea

            # schema generated by a GUI
            # or directly written in a .py config file
            # or whatever

            schema = {'turbine1': {'class': 'Turbine',
            'upstream' : ('frobnicator2' ,),
            'downstream' : () # nothing,
            },
            'frobnicator2' : {'class' : 'Frobnicator',
            'upstream' : (),
            'downstream' : ('frobnicator2' ,),
            },
            }

            # code:

            def get_class_by_na me(name):
            return globals()[name]

            def chain_from_sche ma(schema):
            objects = {}
            for name, desc in schema:
            klass = get_class_by_na me(desc['class'])
            objects[name] = klass()
            for name, desc in schema:
            target = objects[name]
            ups = [objects[upname] for upname in desc['upstream']]
            downs = [objects[downname] for downname in desc['downstream']]
            target.links(up stream=ups, downstream=down s)
            return objects


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

            Comment

            • davehowey@f2s.com

              #21
              Re: using names before they're defined

              Hiya

              Could you just talk me through this... is it:
              schema = {'turbine1': {'class': 'Turbine',
              'upstream' : ('frobnicator2' ,),
              'downstream' : () # nothing,
              },
              'frobnicator2' : {'class' : 'Frobnicator',
              'upstream' : (),
              'downstream' : ('frobnicator2' ,),
              },
              }
              >
              ok, so schema is a dictionary of different components, defining what
              class they are and what they're connected to.
              def get_class_by_na me(name):
              return globals()[name]
              what does this function do exactly?
              def chain_from_sche ma(schema):
              objects = {} # so objects is our list of objects ?
              for name, desc in schema: # can you step through a dictionary like this?
              klass = get_class_by_na me(desc['class']) # does this create an object called klass?
              objects[name] = klass()

              sorry for being dim..
              Dave

              Comment

              • Larry Bates

                #22
                Re: using names before they're defined

                I don't know if you saw my earlier post but something like
                this has worked for me.

                What about something like:

                supply = supply()
                compressor = compressor(supp ly)
                combuster1= combuster(compr essor)
                combuster2= combuster(compr essor)
                compressor.appe nd(combuster1)
                compressor.appe nd(combuster2)

                or perhaps

                compressor.exte nd([combuster1, combuster2])


                turbine = turbine(combust er)
                combuster.appen d(turbine)


                If you implement .append and .extend methods
                on your classes they will allow you to append single
                downstream objects or extend with a list of them.
                Just keep a list self.downstream and append/extend
                it. IMHO it makes what is going on intuitively obvious.

                -Larry Bates

                davehowey@f2s.c om wrote:
                Bruno,
                >
                Thanks. An issue is that I need to be able to link multiple objects to
                a single object etc.
                Say for example using the previous wording, I might have compressor -
                multiple combustors - turbine
                >
                this complicates things slightly.
                >
                my current thought is to do a two stage initialisation
                >
                1. create the objects
                compressor = compressor()
                combuster1 = combuster()
                combuster2 = combuster()
                >
                etc
                >
                2. link them
                compressor.link (downstream = [combuster1, combuster2])
                combuster1.link (upstream = compressor)
                etc.
                >
                hmmmm I need to give it some more though, particularly how I solve all
                the linked objects (which is the point)
                >
                Dave
                >

                Comment

                • Bruno Desthuilliers

                  #23
                  Re: using names before they're defined

                  davehowey@f2s.c om a écrit :
                  Hiya
                  >
                  Could you just talk me through this... is it:
                  >
                  >
                  >>schema = {'turbine1': {'class': 'Turbine',
                  > 'upstream' : ('frobnicator2' ,),
                  > 'downstream' : () # nothing,
                  > },
                  > 'frobnicator2' : {'class' : 'Frobnicator',
                  > 'upstream' : (),
                  > 'downstream' : ('frobnicator2' ,),
                  > },
                  > }
                  >>
                  >
                  >
                  ok, so schema is a dictionary of different components, defining what
                  class they are and what they're connected to.
                  Yeps.

                  Note that it could as well be a list of tuple or anything like this, ie:
                  schema = [
                  ('turbine1', 'Turbine', ('frobnicator2' ,), ()),
                  ('frobnicator2' , 'Frobnicator', (), ('frobnicator2' ,),
                  ]

                  I choose a dict for readability.

                  Also, I gave the example using Python code as 'config' format, but any
                  structured enough text format could do, ie JSON, XML, or even ini-like:

                  # schema.ini
                  objects = turbine1, frobnicator2

                  [turbine1]
                  class=Turbine
                  upstream=frobni cator2
                  downstream=

                  [frobnicator2]
                  class=Frobnicat or
                  upstream=
                  downstream=turb ine


                  Now you just read the file with the standard config parser and build
                  your chain from it... (implementation left as an exercice...)

                  >>def get_class_by_na me(name):
                  > return globals()[name]
                  >
                  >
                  what does this function do exactly?
                  Q&D way to retrieve the class object (Python's classes are themselves
                  objects) known by it's name (as a string).

                  globals() returns the module's namespace as a dict object with
                  'name':object pairs. This code assume that the name is available in the
                  current module's namespace, but could be improved to handle needed
                  imports etc.
                  >>def chain_from_sche ma(schema):
                  > objects = {} # so objects is our list of objects ?
                  > for name, desc in schema:
                  # can you step through a dictionary like this?

                  Nope, sorry, it's a mistake I do over and over. It's of course:;
                  for name, desc in schema.items():

                  (note that you can iterate over a dict's keys with 'for k in thedict:' )
                  > klass = get_class_by_na me(desc['class'])
                  # does this create an object called klass?

                  Nope, it binds the class object (retrieved by get_class_by_na me()) to
                  the local name 'klass' ('class' is a reserved name).
                  > objects[name] = klass()
                  >
                  sorry for being dim..
                  Where ?

                  Comment

                  • davehowey@f2s.com

                    #24
                    Re: using names before they're defined

                    Hi
                    Also, I gave the example using Python code as 'config' format, but any
                    structured enough text format could do, ie JSON, XML, or even ini-like:
                    >
                    # schema.ini
                    objects = turbine1, frobnicator2
                    >
                    [turbine1]
                    class=Turbine
                    upstream=frobni cator2
                    downstream=
                    >
                    yes, I like the idea of using .ini type file format or XML, very much.
                    There are parser available which will automatically building python
                    objects from this, won't they (like configparser)? I'll have to get
                    reading over the weekend...
                    >def get_class_by_na me(name):
                    return globals()[name]
                    >
                    Q&D way to retrieve the class object (Python's classes are themselves
                    objects) known by it's name (as a string).
                    ok, so it actually returns the class object itself.
                    One thing that confuses me is that objects have a name (self.name) but
                    object instances also have a name (e.g. myspecialturbin e = turbine(...)
                    ---- how do I discover the name 'myspecialturbi ne' ?). And object
                    instances have a class name too ('turbine'). Aaargh, too many names!
                    what if just want to know what the name of the instance is (in this
                    case 'myspecialturbi ne'?)

                    Right. I'll have a go at pulling all this together over the weekend
                    hopefully. Hurrah! Thanks for all the help, to everyone.
                    Dave

                    Comment

                    • Bruno Desthuilliers

                      #25
                      Re: using names before they're defined

                      davehowey@f2s.c om wrote:
                      Hi
                      >
                      >
                      (snip)
                      >
                      >>>>def get_class_by_na me(name):
                      >>>return globals()[name]
                      >>>
                      >>Q&D way to retrieve the class object (Python's classes are themselves
                      >>objects) known by it's name (as a string).
                      >
                      >
                      ok, so it actually returns the class object itself.
                      One thing that confuses me is that objects have a name (self.name)
                      They dont - unless you give them one:
                      >>class Foo(object): pass
                      ....
                      >>Foo.name
                      Traceback (most recent call last):
                      File "<stdin>", line 1, in ?
                      AttributeError: type object 'Foo' has no attribute 'name'
                      >>f = Foo()
                      >>f.name
                      Traceback (most recent call last):
                      File "<stdin>", line 1, in ?
                      AttributeError: 'Foo' object has no attribute 'name'
                      >>>
                      classes, functions and modules have a __name__ attribute, but that's
                      something else...
                      but
                      object instances also have a name (e.g. myspecialturbin e = turbine(...)
                      Actually, this is the other way round: names refers ('are bound to')
                      objects. Think of namespaces (the global or local one...) as dicts
                      holding name:ref-to-object pairs (that's mostly what they are FWIW).
                      Different names can refer to the same object. The object itself doesn't
                      know anything about this.
                      ---- how do I discover the name 'myspecialturbi ne' ?).
                      From within the object refered by this name ? Short answer : you can't.
                      And object
                      instances have a class name too ('turbine').
                      Nope, they have a class, which itself as a __name__ attribute, which is
                      the name that was used when "creating" the class object (ie: usually
                      when the 'class' statement is eval'd at module load time).
                      Aaargh, too many names!
                      what if just want to know what the name of the instance is (in this
                      case 'myspecialturbi ne'?)
                      you just named it so yourself, ie:
                      myspecialturbin e = SpecialTurbine( )

                      Else, no way. You can of course give a name when instanciating the object:

                      class Named(object):
                      def __init__(self, name):
                      self.name = name

                      n1 = Named('n1')
                      print n1.name
                      =n1

                      But this doesn't mean there's any correspondance between this name and a
                      name in the current (or any other) namespace:

                      toto = n1
                      n1 = "lalala"
                      print toto.name
                      =n1

                      locals()[toto.name] is toto
                      =False


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

                      Comment

                      • Nick Vatamaniuc

                        #26
                        Re: using names before they're defined

                        Dave,

                        Sometimes generating classes from .ini or XML files is not the best
                        way. You are just translating one language into another and are making
                        bigger headaches for your self. It is certainly cool and bragable to
                        say that "my classes get generated on the fly from XML" but Python is
                        terse and reasonable enough to just write it in Python. In other words
                        instead of saying <turbine<power> 2MW</power></turbinejust write
                        some Python code that instantiates a turbine with a 2MW power based on
                        your class. Then you can evaluate Python code in Python and you even
                        got your on-the-fly generation.
                        As a general rule, I would say to think 3 times before touching XML in
                        Python unless you are absolutely forced to. Config .ini files can be
                        more acceptable but Python is still best. Why write
                        ;;My turbine class
                        [turbine]
                        power=2MW
                        speed=800rpm
                        ....
                        when you can just say:
                        #my turbine class
                        t=Turbine( power="2MW", \
                        speed="800rpm", \
                        ...
                        First case is a little shorter but then you have to use a parser for it
                        while in the second case you just execute the file, and besides, you
                        can edit it with any Python editor.

                        Hope this helps,
                        Nick V.


                        davehowey@f2s.c om wrote:
                        Hi
                        >
                        Also, I gave the example using Python code as 'config' format, but any
                        structured enough text format could do, ie JSON, XML, or even ini-like:

                        # schema.ini
                        objects = turbine1, frobnicator2

                        [turbine1]
                        class=Turbine
                        upstream=frobni cator2
                        downstream=
                        >
                        yes, I like the idea of using .ini type file format or XML, very much.
                        There are parser available which will automatically building python
                        objects from this, won't they (like configparser)? I'll have to get
                        reading over the weekend...
                        >
                        >>def get_class_by_na me(name):
                        > return globals()[name]
                        >
                        Q&D way to retrieve the class object (Python's classes are themselves
                        objects) known by it's name (as a string).
                        >
                        ok, so it actually returns the class object itself.
                        One thing that confuses me is that objects have a name (self.name) but
                        object instances also have a name (e.g. myspecialturbin e = turbine(...)
                        ---- how do I discover the name 'myspecialturbi ne' ?). And object
                        instances have a class name too ('turbine'). Aaargh, too many names!
                        what if just want to know what the name of the instance is (in this
                        case 'myspecialturbi ne'?)
                        >
                        Right. I'll have a go at pulling all this together over the weekend
                        hopefully. Hurrah! Thanks for all the help, to everyone.
                        Dave

                        Comment

                        • Patrick Maupin

                          #27
                          Re: using names before they're defined


                          davehowey@f2s.c om wrote:
                          I have a problem. I'm writing a simulation program with a number of
                          mechanical components represented as objects. When I create instances
                          of objects, I need to reference (link) each object to the objects
                          upstream and downstream of it, i.e.
                          >
                          supply = supply()
                          compressor = compressor(down stream=combusto r, upstream=supply )
                          combuster = combuster(downs tream=turbine, upstream=compre ssor)
                          etc.
                          >
                          the problem with this is that I reference 'combustor' before is it
                          created. If I swap the 2nd and 3rd lines I get the same problem
                          (compressor is referenced before creation).
                          >
                          >
                          aargh!!! any ideas on getting around this?
                          >
                          Dave
                          I have done similar things in the past. One useful trick is to define
                          a special class for connections, create a single instance of this
                          class, and make all your connections as attributes of this instance.
                          For example:

                          world = Simulation()

                          world.supply = Supply()
                          world.compresso r = Compressor(down stream=world.cu mbustor,
                          upstream=world. supply)
                          world.cumbuster = Combuster(downs tream=world.tur bine,
                          upstream=world. compressor)

                          Because Python lets you control attribute access to your simulation
                          world object, it is relatively easy to make proxy objects for
                          attributes which don't yet exist via __getattr__, and then to insert
                          the real object into the proxy via __setattr__.

                          Alternatively, the script (using the same syntax as shown above!) can
                          simply collect all the connection information when it is run, then make
                          a "real" structure later. This works best if your simulation objects
                          (Supply, Compressor, Cumbuster) allow setting of the connection
                          attributes after instantiation.

                          Regards,
                          Pat

                          Comment

                          • Bruno Desthuilliers

                            #28
                            Re: using names before they're defined

                            Nick Vatamaniuc wrote:
                            Dave,
                            >
                            Sometimes generating classes from .ini or XML files is not the best
                            way. You are just translating one language into another and are making
                            bigger headaches for your self. It is certainly cool and bragable to
                            say that "my classes get generated on the fly from XML" but Python is
                            terse and reasonable enough to just write it in Python. In other words
                            instead of saying <turbine<power> 2MW</power></turbinejust write
                            some Python code that instantiates a turbine with a 2MW power based on
                            your class. Then you can evaluate Python code in Python and you even
                            got your on-the-fly generation.
                            As a general rule, I would say to think 3 times before touching XML in
                            Python unless you are absolutely forced to. Config .ini files can be
                            more acceptable but Python is still best. Why write
                            ;;My turbine class
                            [turbine]
                            power=2MW
                            speed=800rpm
                            ...
                            when you can just say:
                            #my turbine class
                            t=Turbine( power="2MW", \
                            speed="800rpm", \
                            ...
                            First case is a little shorter but then you have to use a parser for it
                            There's one builtin.
                            while in the second case you just execute the file, and besides, you
                            can edit it with any Python editor.
                            >
                            This is certainly nice when the users are able to write python code, but
                            that's not always the case. Also, it can be dangerous to directly
                            execute user's python code...


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

                            Comment

                            • davehowey@f2s.com

                              #29
                              Re: using names before they're defined

                              First case is a little shorter but then you have to use a parser for it
                              >
                              There's one builtin.
                              do you mean 'configparser'? I'm just trying to figure out how this
                              works. Does it generate objects from the config file automatically?

                              Dave

                              Comment

                              • Bruno Desthuilliers

                                #30
                                Re: using names before they're defined

                                davehowey@f2s.c om a écrit :
                                >>>First case is a little shorter but then you have to use a parser for it
                                >>
                                >>There's one builtin.
                                >
                                >
                                do you mean 'configparser'?
                                Yes.
                                I'm just trying to figure out how this
                                works.
                                One nice thing with Python is the interactive python shell. It makes
                                exploring a package a breeze.
                                Does it generate objects from the config file automatically?
                                It generates a representation of the config file as a Python object
                                composed of sections and options. The documentation should get you started.

                                Comment

                                Working...