Generating modul classes with eval

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

    #1

    Generating modul classes with eval

    Hello!

    I was fooling around with creating classes for a module with eval,
    something like:

    MyModule.py:

    class Base:
    init(self, name):
    self._name = name

    for myclass in ['A', 'B', 'C']:
    code="class %s(Base):\n\tin it(self, name='%s')\n\t\ tsuper(%s,
    self).__init(na me=name)\n"%dic t(myclass, myclass.lower() , myclass())
    ... codeop and eval stuff ...
    a=A()
    print a

    that gives: <class '__main__.A'>, but I want MyModule.A ;-)

    Can someone give me a hint how to create classes in a module with eval
    and codeop so that they exist like the code was written in?

    Thanks,
    AXEL.

  • Steve Holden

    #2
    Re: Generating modul classes with eval

    Axel Straschil wrote:
    [color=blue]
    > Hello!
    >
    > I was fooling around with creating classes for a module with eval,
    > something like:
    >
    > MyModule.py:
    >
    > class Base:
    > init(self, name):
    > self._name = name
    >
    > for myclass in ['A', 'B', 'C']:
    > code="class %s(Base):\n\tin it(self, name='%s')\n\t\ tsuper(%s,
    > self).__init(na me=name)\n"%dic t(myclass, myclass.lower() , myclass())
    > ... codeop and eval stuff ...
    > a=A()
    > print a
    >
    > that gives: <class '__main__.A'>, but I want MyModule.A ;-)
    >
    > Can someone give me a hint how to create classes in a module with eval
    > and codeop so that they exist like the code was written in?
    >
    > Thanks,
    > AXEL.
    >[/color]
    You could try just importing the module - then, when it runs, its name
    won't be "__main__" but "MyModule".

    regards
    Steve
    --
    Meet the Python developers and your c.l.py favorites March 23-25
    Come to PyCon DC 2005 http://www.python.org/pycon/2005/
    Steve Holden http://www.holdenweb.com/

    Comment

    • Jeremy Bowers

      #3
      Re: Generating modul classes with eval

      On Wed, 02 Feb 2005 20:49:07 +0000, Axel Straschil wrote:

      You are doing several things wrong.
      [color=blue]
      > I was fooling around with creating classes for a module with eval,[/color]

      You shouldn't create classes with eval, because you don't need to.

      "class" isn't a declaration, it is an executable statement that creates
      new classes. We'll get into that momentarily...
      [color=blue]
      > something like:
      >
      > MyModule.py:
      >
      > class Base:
      > init(self, name):
      > self._name = name[/color]

      Your "init" function needs to be spelled "__init__", or it will not be
      automatically called.

      You also did not correctly use "def" to create your function. When posting
      to the newsgroup, try to use real code that you have actually executed.
      [color=blue]
      > that gives: <class '__main__.A'>, but I want MyModule.A ;-)[/color]

      No, it won't, since your code has syntax errors in it. Post the code you
      actually ran.

      That said, "__main__" indicates you ran it in the interactive shell. That
      is correct, and won't change. Also, the name printing the class gives is
      only very rarely important; overall you shouldn't be using that.

      I'll start with giving you this:

      -------

      import sys
      module = sys.modules[__name__]

      class Base:
      def __init__(self, name):
      self._name = name

      for myclass in ['A', 'B', 'C']:
      class Tmp(Base):
      myname = myclass
      def __init__(self):
      Base.__init__(s elf, self.myname)

      setattr(module, myclass, Tmp)

      -------

      Note that we don't need eval anywhere.

      But I'd suggest that this is more likely what you want:

      -------

      class Base:
      def __init__(self, name):
      self._name = name

      myClasses = {}

      for className in ['A', 'B', 'C']:
      class Tmp(Base):
      myname = className
      def __init__(self):
      Base.__init__(s elf, self.myname)

      myClasses[className] = Tmp

      -------

      Adding things straight to modules is rarely worth it; you're better off
      just collecting them somewhere.

      There are too many differences to go over here between my code and yours,
      so if you have questions, please ask. One of the reasons you don't want
      eval is that I had to give up trying to read your class code!

      Finally, while such generated classes do have their use, I'd ask what you
      are planning to do with this; odds are, you don't need it.

      In general, unless you are using "eval" to literally execute user supplied
      input, you *almost* certainly don't need it.

      A downside of my approach is that printing all three classes will say the
      class name is "Tmp". Since, as I said, you really shouldn't care about
      that, I don't care to try to fix it :-) If you can provide a compelling
      reason why you need that, somebody here can help you with that.

      Comment

      • Jeremy Bowers

        #4
        Re: Generating modul classes with eval

        On Wed, 02 Feb 2005 16:20:41 -0500, Jeremy Bowers wrote:[color=blue]
        > That said, "__main__" indicates you ran it in the interactive shell.[/color]

        Or ran it directly on the command line. Duh. I thought that clause really
        loudly, but I guess I never actually typed it.

        Comment

        • Axel Straschil

          #5
          Re: Generating modul classes with eval

          Hello!
          [color=blue]
          > Note that we don't need eval anywhere.[/color]

          Uuups, that looks realy cool! Thanks for that!

          Im fooling around with generating html-tags. As there are only two kind
          of html tags, one who can nest chields, and one who cant, i wantet to
          play arround with something like:

          I've got two base classes, _Tag and _ContainerTag (for tags which can
          nest tags). Instead of getting an htmltag with _Tag(name='html '), I
          want to have a class for each html-tag. So, I thought of creating that
          classes dynamicly.

          my now (nearly) working code is:

          class _Tag(object):
          def __init__(self, name, flags=None, **props):
          [...]

          class _ContainerTag(_ Tag):
          def __init__(self, name, contents=None, flags=None, **props):
          super(_Containe rTag, self).__init__( name=name, flags=flags, **props)
          self._contents = coalesce(conten ts, [])


          _module_name = sys.modules[__name__]

          class_dic = {}
          class_dic['Br'] = _Tag
          class_dic['Hr'] = _Tag
          class_dic['Html'] = _ContainerTag
          class_dic['Table'] = _ContainerTag

          for class_name, class_base in class_dic.items ():
          class TmpClass(class_ base):
          def __init__(self, **props):
          name = class_name.lowe r()
          #super(TmpClass , self).__init__( name=name, **props)
          class_base.__in it__(self, name=name, **props)
          setattr(_module _name, class_name, TmpClass)

          br = Br()
          print br
          table = Table()
          print table

          br is printed OK, but for table, I get:
          AttributeError: 'TmpClass' object has no attribute '_contents'
          so, it seems that __init__ of _Tag is not called.
          If I try to do the commented line
          super(TmpClass, self).__init__( name=name, **props)
          instead of
          class_base.__in it__(self, name=name, **props)
          I get:
          TypeError: super(type, obj): obj must be an instance or subtype of
          type
          for print table, print br ist processed OK.


          Thanks for help and your perfekt examples,
          AXEL.

          Comment

          Working...