general class functions

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

    #16
    Re: two new wrinkles to the general class!

    syd wrote:
    [color=blue][color=green][color=darkred]
    >>>1) Because I've got many "container" type classes, the best route
    >>>
    >>>[/color][/color]
    >would obviously seem be to subclass each to a general "container" . Ie,
    >
    >class Library_A(Conta iner): ...
    >class Library_B(Conta iner): ...
    >
    >The problem: in the current setup, a library_a.get_c ontinent('Europ e')
    >would pass back an instance of Container and *not* Library_A. The
    >obvious implication is that any attributes/method specific to Library_A
    >are gone.
    >[/color]

    As I understand it, your object's (most derived) type will be stored as
    self.__class__. So, in order to have Library_A create more Library_A
    instances, and Library_B create more Library_B instances, you can
    instead do something like:

    new_copy = self.__class__( )

    [color=blue]
    >2) I've got a bunch of "get_foo" type things where "foo" is not an
    >
    >
    >attribute of the component class but rather a method. [...]
    >
    >Above, we use getattr() to grab the attribute on-the-fly. Can we grab
    >a method on-the-fly, too?
    >[/color]

    Sure -- methods are just attributes that happen to be callable. You get
    a method reference in the same way that you get any attribute, and you
    call it the same way that you call any function reference:

    method = Collection.get_ foo('bar')
    method()

    will call whatever method get_foo('bar') returns.

    Jeff Shannon
    Technician/Programmer
    Credit International

    Comment

    • syd

      #17
      Re: two new wrinkles to the general class!

      > new_copy = self.__class__( )

      Awesome! I didn't know I could call it like that... thanks, Jeff.
      [color=blue]
      > method = Collection.get_ foo('bar')
      > method()[/color]

      I suppose I knew that, but I wasn't thinking. I can do something like
      (for nation as a component of library):

      (criteria='foo' or 'bar' or whatever... grabbed from __getattr__)
      isMethodString= 'is'+criteria
      isMethod=getatt r(library,isMet hodString)

      then the criteria for inclusion becomes when isMethod()==Tru e

      ----------------------------------------------

      One final question that I can't seem to get, but I know I should be
      able to do:

      Given a Library class with possible component class types Nation_A,
      Nation_B, and so forth where type(Nation_A)< >type(Nation_B) . If I had
      the string 'Nation_B', how could I get an empty class Nation_B?

      ie,
      dir()=['Library','Nati on_A','Nation_B ',...]
      desiredEmptyCla ssString=dir[2]
      desiredEmptyCla ss=getEmptyClas sFromString(des iredEmptyClassS tring)
      Does a "getEmptyClassF romString" method exist?

      Comment

      • Jeff Shannon

        #18
        Re: two new wrinkles to the general class!

        syd wrote:
        [color=blue]
        >One final question that I can't seem to get, but I know I should be
        >able to do:
        >
        >Given a Library class with possible component class types Nation_A,
        >Nation_B, and so forth where type(Nation_A)< >type(Nation_B) . If I had
        >the string 'Nation_B', how could I get an empty class Nation_B?
        >
        >ie,
        >dir()=['Library','Nati on_A','Nation_B ',...]
        >desiredEmptyCl assString=dir[2]
        >desiredEmptyCl ass=getEmptyCla ssFromString(de siredEmptyClass String)
        >Does a "getEmptyClassF romString" method exist?
        >
        >[/color]

        Not directly, but it can be faked.

        It's easiest if you're getting the class from an imported module.
        Remember that a module is just another object, and a class object is
        just another callable.

        import MyLibrary

        desired_class = getattr(MyLibra ry, desired_empty_c lass_string)
        myobject = desired_class()

        It's a bit trickier if the class is defined in the current module, but
        the principle is similar. You just need a way to look up an attribute
        in the *current* module's namespace, rather than in another module's
        namespace. As it turns out, the globals() built-in function will return
        the current global namespace, which is actually a dictionary.

        desired_class = globals()[desired_empty_c lass_string]
        myobject = desired_class()

        Personally, I feel nervous any time I have code that uses something like
        globals() -- I feel like I'm starting to poke at internals. It should
        be completely safe, especially using it in a read-only way like this,
        but just out of inherent cautiousness I prefer to avoid it when I can.
        So, I'd be likely to put all of the interesting class objects into my
        own dict, and call them from there.

        LibraryFactory = { 'Library': Library, 'Nation_A':Nati on_A, ... }

        myobject = LibraryFactory[desired_empty_c lass_string]()

        Note that, if you really are selecting the string via an integer index
        into a list, you could instead key this dictionary off of the integers:

        LibraryFactory = {0:Library, 1:Nation_A, 2:Nation_B, ...}
        myobject = LibraryFactory[index]()

        Using a dict like this makes me feel a bit more comfortable than using
        globals() (though I realize that this is not necessarily a matter of
        rational reasoning), and it also seems to me to be a bit more
        encapsulated (relevant items are specifically gathered in one particular
        place, rather than just being scattered about the global namespace and
        picked up as needed). But using globals() is a perfectly viable option
        as well.

        Jeff Shannon
        Technician/Programmer
        Credit International

        Comment

        • syd

          #19
          Re: two new wrinkles to the general class!

          Good thinking! I'll give my take on the two suggestions below...
          [color=blue]
          > desired_class = globals()[desired_empty_c lass_string]
          > myobject = desired_class()[/color]

          I understands your hesitation about using this, although this is
          relatively more portable in that you don't need to have the dictionary
          passed around. One limitation is subclassing, ie, you could not do
          globals()['Library.Nation _A']. You can get around this by splitting the
          string by '.' and recursively using getattr() to get subclasses in your
          split list.
          [color=blue]
          > LibraryFactory = { 'Library': Library, 'Nation_A':Nati on_A, ... }[/color]
          [color=blue]
          > myobject = LibraryFactory[desired_empty_c lass_string]()[/color]

          This works well, too, as long as you define this outside the classes
          after you've defined everything. This limits portability a bit though,
          because you a 'from myClasses import Library' would not grab the
          LibraryFactory.

          --------------------------------------------------
          On a related note, is there a good way from within a class to get the
          name in the simple form? Ie,

          # str(library.__c lass__)
          "<class 'foo2.Library'> "

          I'm looking for something more along these lines:
          # hypotheticalMet hod(library)
          'Library'

          Comment

          • Steven Bethard

            #20
            name of a class (WAS two new wrinkles to the general class!)

            syd <syd.diamond <at> gmail.com> writes:[color=blue]
            >
            > On a related note, is there a good way from within a class to get the
            > name in the simple form?[/color]


            Does this work for you?
            [color=blue][color=green][color=darkred]
            >>> class C(object):[/color][/color][/color]
            .... pass
            ....[color=blue][color=green][color=darkred]
            >>> C().__class__._ _name__[/color][/color][/color]
            'C'

            Steve

            Comment

            • syd

              #21
              Re: general class functions

              Thanks for everyone's help on this thread. Right now, I've got a
              general class ("Container" ) holding items that can be accessed by item
              attribute values through __getattr__ functions.

              My various classes use Container as a subclass. Right now, I keep both
              classes in the same file, and everything works great. However, when I
              move Container to a separate file and "from myClasses import Container"
              to use this general class, I seem to lose all of the __getattr__
              functionality while retaining the other functions in Container.
              Does anyone know why this happens and how I can get around this??

              Comment

              Working...