niXforums Forum Index
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   PreferencesPreferences   Log in to check your private messagesLog in to check your private messages   Log inLog in 
·  nixdoc.net ·  man pages ·  Linux HOWTOs ·  FreeBSD Tips ·  Forums
navigation Forum index » Programming » python
Generating modul classes with eval
Post new topic   Reply to topic Page 1 of 1 [7 Posts] View previous topic :: View next topic
Author Message
Axel Straschil
*nix forums beginner


Joined: 11 Apr 2005
Posts: 15

PostPosted: Thu Feb 03, 2005 12:59 pm    Post subject: Re: Generating modul classes with eval Reply with quote

Hello!

Quote:
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: <table><tr><br/></tr></table>

Thanks,
AXEL.
Back to top
Peter Otten
*nix forums Guru


Joined: 20 Feb 2005
Posts: 464

PostPosted: Thu Feb 03, 2005 11:18 am    Post subject: Re: Generating modul classes with eval Reply with quote

Axel Straschil wrote:

Quote:
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:

Quote:
classes = []
for text in ["alpha", "beta"]:
.... class T:

.... def __init__(self): print text
.... classes.append(T)
....
Quote:
classes[0] is classes[1]
False # two distinct classes, as expected
classes[0]()
beta

<__main__.T instance at 0x402a9e2c>
Quote:
classes[1]()
beta

<__main__.T instance at 0x402a9f8c>

And now the proof that you are actually accessing the global variable:

Quote:
text = "gamma"
classes[0]()
gamma

<__main__.T instance at 0x402a9f8c>

One way to fix this is to introduce a factory function:

Quote:
def make_class(text):
.... class T:

.... def __init__(self): print text
.... return T
....
Quote:
classes = []
for text in ["alpha", "beta"]:
.... classes.append(make_class(text))

....
Quote:
classes[0]()
alpha

<__main__.T instance at 0x402a9e4c>
Quote:
classes[1]()
beta

<__main__.T instance at 0x402a9f8c>
Quote:



Peter
Back to top
Axel Straschil
*nix forums beginner


Joined: 11 Apr 2005
Posts: 15

PostPosted: Thu Feb 03, 2005 9:26 am    Post subject: Re: Generating modul classes with eval Reply with quote

Hello!

Quote:
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.
Back to top
Steve Holden
*nix forums Guru


Joined: 22 Feb 2005
Posts: 1255

PostPosted: Wed Feb 02, 2005 8:49 pm    Post subject: Re: Generating modul classes with eval Reply with quote

Axel Straschil wrote:

Quote:
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/
Back to top
Jeremy Bowers
*nix forums Guru Wannabe


Joined: 23 Feb 2005
Posts: 129

PostPosted: Wed Feb 02, 2005 8:49 pm    Post subject: Re: Generating modul classes with eval Reply with quote

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

You are doing several things wrong.

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

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...

Quote:
something like:

MyModule.py:

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

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.

Quote:
that gives: <class '__main__.A'>, but I want MyModule.A Wink

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__(self, 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__(self, 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 Smile If you can provide a compelling
reason why you need that, somebody here can help you with that.
Back to top
Jeremy Bowers
*nix forums Guru Wannabe


Joined: 23 Feb 2005
Posts: 129

PostPosted: Wed Feb 02, 2005 8:49 pm    Post subject: Re: Generating modul classes with eval Reply with quote

On Wed, 02 Feb 2005 16:20:41 -0500, Jeremy Bowers wrote:
Quote:
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.
Back to top
Axel Straschil
*nix forums beginner


Joined: 11 Apr 2005
Posts: 15

PostPosted: Wed Feb 02, 2005 8:49 pm    Post subject: Generating modul classes with eval Reply with quote

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.
Back to top
Google

Back to top
Display posts from previous:   
Post new topic   Reply to topic Page 1 of 1 [7 Posts] View previous topic :: View next topic
The time now is Thu Jan 08, 2009 11:40 pm | All times are GMT
navigation Forum index » Programming » python
Jump to:  

Similar Topics
Topic Author Forum Replies Last Post
No new posts Warning when new attributes are added to classes at run time Matthew Wilson python 7 Wed Jul 19, 2006 8:42 pm
No new posts Partial classes Sanjay python 26 Wed Jul 19, 2006 6:10 am
No new posts Which Advanced classes to take for oracle 10g OCM exam? gnu Server 0 Mon Jul 17, 2006 11:56 am
No new posts assignment operator for classes with const data scroopy C++ 19 Mon Jul 17, 2006 8:48 am
No new posts nested rested classes? Len Conrad Postfix 1 Sun Jul 16, 2006 12:05 am

Debt Help | Free Ringtone | Loans | Repair Bad Credit | Loans
Copyright © 2004-2005 DeniX Solutions SRL
 
Other DeniX Solutions sites: Unix/Linux blog |  electronics forum |  medicine forum |  science forum | 
Privacy Policy


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.2036s ][ Queries: 20 (0.0935s) ][ GZIP on - Debug on ]