using exec() to instantiate a new object.

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

    using exec() to instantiate a new object.

    Hello,

    I'm trying to teach myself OOP to do a data project involving
    hierarchical data structures.

    I've come up with an analogy for testing involving objects for
    continents, countries, and states where each object contains some
    attributes one of which is a list of objects. E.g. a country will
    contain an attribute population and another countries which is a list
    of country objects. Anyways, here is what I came up with at first:

    class continent(objec t):
    def __init__(self,c ontinent_name):
    self.name = continent_name
    self.countries = []
    def addCountry(self ,country_name):
    self.countries. append(country_ name)
    def listCountries(s elf):
    for country in self.countries:
    print country.name, "pop:",country. population,", states:"
    country.listSta tes()

    class country(object) :
    def __init__(self,n ame):
    self.name = name
    self.population = 0
    self.states = []
    def addState(self,s tate_name):
    self.states.app end(state_name)

    def listStates(self ):
    for state in self.states:
    print " ",state.name,"p op:",state.popu lation
    state.stateInfo ()

    class state(object):
    def __init__(self,s tate_name):
    self.name = state_name
    self.color = 'unknown'
    self.counties = []
    self.population = 0
    def addCounty(self, county):
    self.counties.a ppend(county)
    def stateInfo(self) :
    print " color:",self.co lor
    print " counties",self. counties[:]


    NAm = continent('NAm' )
    usa= country('usa')
    canada = country('canada ')
    mexico = country('mexico ')
    florida = state('florida' )
    maine = state('maine')
    california = state('californ ia')
    quebec = state('quebec')

    NAm.addCountry( usa)
    NAm.addCountry( canada)
    NAm.addCountry( mexico)
    usa.addState(ma ine)
    usa.addState(ca lifornia)
    usa.addState(fl orida)
    canada.addState (quebec)
    florida.addCoun ty('dade')
    florida.addCoun ty('broward')
    maine.addCounty ('hancock')
    california.addC ounty('marin')

    florida.populat ion = 1000
    california.popu lation = 2000
    maine.populatio n = 500
    quebec.populati on = 1000
    florida.color = maine.color = california.colo r = 'blue'
    NAm.listCountri es()

    --------------------------------------------------------------------------
    so this works but is far more cumbersome than it should be.
    I would like to create an object when I add it

    so I wouldn't have to do:
    usa= country('usa')
    NAm.addCountry( usa)

    I could just do
    NAm.addCountry( 'usa')

    which would first create a country object then add it to a countries
    list

    to do this I tried:

    def addCountry(self ,country_name):
    # create an instance of country
    exec(country_na me + "= country('" + country_name + "')")
    # Add this new instance of a country to a list
    exec("self.coun tries.append(" + country_name + ")")

    Which doesn't give an error, but doesn't seem to create an instance of
    the country object.

    Does this make sense? Can this be done?
    For my real project, I won't know the names and quantities of objects.
    They will be highly variable and based on data contained in the
    "parent" object.

    Thanks
  • Patrick Mullen

    #2
    Re: using exec() to instantiate a new object.

    On Fri, Nov 7, 2008 at 2:23 PM, RyanN <Ryan.Neve@gmai l.comwrote:
    >
    to do this I tried:
    >
    def addCountry(self ,country_name):
    # create an instance of country
    exec(country_na me + "= country('" + country_name + "')")
    # Add this new instance of a country to a list
    exec("self.coun tries.append(" + country_name + ")")
    >
    Don't use exec. It's quite dangerous, and in your case is making
    things much more complex than necessary. A much simpler way to do
    what you want:

    def addCountry(self ,country_name):
    self.countries. append(country( country_name))

    There is no need to bind the result of "country(countr y_name)" to a name at all.

    Comment

    • Aaron Brady

      #3
      Re: using exec() to instantiate a new object.

      On Nov 7, 4:23 pm, RyanN <Ryan.N...@gmai l.comwrote:
      Hello,
      >
      I'm trying to teach myself OOP to do a data project involving
      hierarchical data structures.
      >
      I've come up with an analogy for testing involving objects for
      continents, countries, and states where each object contains some
      attributes one of which is a list of objects. E.g. a country will
      contain an attribute population and another countries which is a list
      of country objects. Anyways, here is what I came up with at first:
      snip
      >
      NAm = continent('NAm' )
      usa= country('usa')
      canada = country('canada ')
      mexico = country('mexico ')
      florida = state('florida' )
      maine = state('maine')
      california = state('californ ia')
      quebec = state('quebec')
      >
      NAm.addCountry( usa)
      NAm.addCountry( canada)
      NAm.addCountry( mexico)
      usa.addState(ma ine)
      usa.addState(ca lifornia)
      usa.addState(fl orida)
      canada.addState (quebec)
      florida.addCoun ty('dade')
      florida.addCoun ty('broward')
      maine.addCounty ('hancock')
      california.addC ounty('marin')
      snip
      so this works but is far more cumbersome than it should be.
      I would like to create an object when I add it
      >
      so I wouldn't have to do:
      usa= country('usa')
      NAm.addCountry( usa)
      >
      I could just do
      NAm.addCountry( 'usa')
      >
      which would first create a country object then add it to a countries
      list
      snip

      One option is to add the names to a blank object as attributes, using
      setattr. Then you can access them in almost the same way... they're
      just in their own namespace. Other options would be to add them to a
      separate dictionary (name -object). This example is kind of cool,
      as well as nicely instructive.
      >>class Blank: pass
      ....
      >>blank= Blank()
      >>class autoname( ):
      .... def __init__( self, name ):
      .... setattr( blank, name, self )
      .... self.name= name
      ....
      >>autoname( 'fried' )
      <__main__.auton ame instance at 0x00B44030>
      >>autoname( 'green' )
      <__main__.auton ame instance at 0x00B44148>
      >>autoname( 'tomatoes' )
      <__main__.auton ame instance at 0x00B44170>
      >>blank.fried
      <__main__.auton ame instance at 0x00B44030>
      >>blank.green
      <__main__.auton ame instance at 0x00B44148>
      >>blank.tomatoe s
      <__main__.auton ame instance at 0x00B44170>
      >>blank
      <__main__.Bla nk instance at 0x00B40FD0>

      You don't have to call the container object 'blank', of course, or its
      class for that matter. I do because that's how it starts out: blank.
      Under the hood it's just a plain old dictionary with extra syntax for
      accessing its contents.

      Comment

      • RyanN

        #4
        Re: using exec() to instantiate a new object.

        Thank you both, I knew there had to be a good way of doing this.

        -Ryan

        Comment

        • RyanN

          #5
          Re: using exec() to instantiate a new object.

          On Nov 10, 7:47 am, RyanN wrote:
          Thank you both, I knew there had to be a good way of doing this.
          >
          -Ryan
          Just an update. I used dictionaries to hold objects and their names.
          I'm beginning to understand better. Now to apply this to my actual
          problem. Here's the code I ended up with:

          class continent(objec t):
          '''
          A continent has a name and a dictionary of countries
          '''
          def __init__(self,c ontinent_name):
          self.name = continent_name
          self.countries = {} #countries is a dictionary of country name
          and object
          def addCountry(self ,country_name,p opulation = 0):
          self.countries[country_name] = country(country _name) #Create a
          new instance of country() and add it to dictionary
          self.countries[country_name].population = population #Set
          country population
          def addState(self,c ountry_name,sta te_name,populat ion = 0):
          if country_name in self.countries:

          self.countries[country_name].addState(state _name,populatio n)
          else: #This state must be in a new country
          self.addCountry (country_name)
          self.addState(c ountry_name,sta te_name,populat ion)
          def listCountries(s elf):
          for a_country in self.countries:
          print a_country,
          "pop:",self.cou ntries[a_country].population,", states:"
          self.countries[a_country].listStates()

          class country(object) :
          '''
          A country has a name, a population and a dictionary of states
          '''
          def __init__(self,n ame):
          self.name = name
          self.population = 0
          self.states = {} #states is a dictionary of state name and
          object
          def addState(self,s tate_name,popul ation = 0):
          self.states[state_name] = state(state_nam e) #Create a new
          instance of state() and add it to dictionary
          self.states[state_name].population = population
          self.population += population #Add this state's population to
          the country's

          def listStates(self ):
          #print self.states[:]
          for a_state in self.states:
          self.states[a_state].stateInfo()

          class state(object):
          '''
          A state has a name, color, and a population
          '''
          def __init__(self,s tate_name):
          self.name = state_name
          self.color = 'unknown'
          self.population = 0
          def stateInfo(self) :
          print " ",self.name,"po p:",self.popula tion,
          "color:",self.c olor

          #Now some examples of how to set and access this information
          NAm = continent('NAm' ) #First we add our continent
          NAm.addCountry( 'canada',700) #Now add a a country to NAm
          NAm.addState('u sa','maine',400 ) #We can add a state even if we haven't
          added the country yet
          NAm.addState('u sa','california ',2000)
          NAm.addState('c anada','quebec' ,700) # I know it's actually a province
          NAm.addState('m exico','QR',550 )
          usa = NAm.countries['usa'] # we can make things easier on ourselves
          usa.population = 5000 #short for: NAm.countries['usa'].population =
          5000
          usa.addState('f lorida') #Another way to add a state, we can set
          population seperately
          NAm.countries['usa'].states['florida'].population = 2000
          for any_state in usa.states: #Set an attribute for all state objects
          usa.states[any_state].color = 'blue'
          NAm.listCountri es() # Generates a report
          # three ways to get to print the same information
          print NAm.countries['usa'].states['maine'].name,
          NAm.countries['usa'].states['maine'].population
          print usa.states['maine'].name, usa.states['maine'].population # We
          already assigned usa to NAm.countries['usa']
          maine = usa.states['maine']
          print maine.name, maine.populatio n

          Comment

          • George Sakkis

            #6
            Re: using exec() to instantiate a new object.

            On Nov 10, 10:37 am, RyanN <Ryan.N...@gmai l.comwrote:
            On Nov 10, 7:47 am, RyanN wrote:
            >
            Thank you both, I knew there had to be a good way of doing this.
            >
            -Ryan
            >
            Just an update. I used dictionaries to hold objects and their names.
            I'm beginning to understand better. Now to apply this to my actual
            problem. Here's the code I ended up with:
            That's fine, but unless you add functionality that *does* actually
            something with all these data, there's not much value going with an
            OO approach compared to using plain old data structures (e.g.
            [default]dicts and [named]tuples).

            George

            Comment

            Working...