Re: Generating modul classes with eval
Hello! Note that we don't need eval anywhere. 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(_ContainerTag, self).__init__(name=name, flags=flags, **props) self._contents = coalesce(contents, []) _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.lower() #super(TmpClass, self).__init__(name=name, **props) class_base.__init__(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.__init__(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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Generating modul classes with eval
Axel Straschil wrote: 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.lower() #super(TmpClass, self).__init__(name=name, **props) class_base.__init__(self, name=name, **props) setattr(_module_name, class_name, TmpClass) While your workaround doesn't balk immediately, it doesn't do the right thing either. After the loop has finished, the global variable TmpClass will be bound to whatever class was created last, and the variable class_base will be bound to that the base class of that same TmpClass. Therefore only this last class is guaranteed to work as expected. A simplified example to demonstrate the binding problem: classes = [] for text in [alpha, beta]: ... class T: ... def __init__(self): print text ... classes.append(T) ... classes[0] is classes[1] False # two distinct classes, as expected classes[0]() beta __main__.T instance at 0x402a9e2c classes[1]() beta __main__.T instance at 0x402a9f8c And now the proof that you are actually accessing the global variable: text = gamma classes[0]() gamma __main__.T instance at 0x402a9f8c One way to fix this is to introduce a factory function: def make_class(text): ... class T: ... def __init__(self): print text ... return T ... classes = [] for text in [alpha, beta]: ... classes.append(make_class(text)) ... classes[0]() alpha __main__.T instance at 0x402a9e4c classes[1]() beta __main__.T instance at 0x402a9f8c Peter -- http://mail.python.org/mailman/listinfo/python-list
Re: Generating modul classes with eval
Hello! After the loop has finished, the global variable TmpClass will be bound to whatever class was created last, and the variable class_base will be bound to that the base class of that same TmpClass. Therefore only this last class is guaranteed to work as expected. Great, now it workes! _module_name = sys.modules[__name__] def _tag_class_factory(name, base): class T(base): def __init__(self, **props): super(T, self).__init__(name=name.lower(), **props) setattr(_module_name, name, T) class_dic = {} class_dic['Br'] = _Tag class_dic['Hr'] = _Tag class_dic['Html'] = _ContainerTag class_dic['Table'] = _ContainerTag class_dic['Td'] = _ContainerTag class_dic['Tr'] = _ContainerTag for name, base in class_dic.items(): _tag_class_factory(name, base) print Table(contents=[Tr(contents=[Br()])]) gives: tabletrbr//tr/table Thanks, AXEL. -- http://mail.python.org/mailman/listinfo/python-list
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\tinit(self, name='%s')\n\t\tsuper(%s, self).__init(name=name)\n%dict(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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Generating modul classes with eval
Axel Straschil wrote: 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\tinit(self, name='%s')\n\t\tsuper(%s, self).__init(name=name)\n%dict(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. 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/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Generating modul classes with eval
On Wed, 02 Feb 2005 16:20:41 -0500, Jeremy Bowers wrote: That said, __main__ indicates you ran it in the interactive shell. Or ran it directly on the command line. Duh. I thought that clause really loudly, but I guess I never actually typed it. -- http://mail.python.org/mailman/listinfo/python-list