[Tutor] Dynamically generated classes

Alan Gauld alan.gauld at btinternet.com
Thu Dec 23 10:13:45 CET 2010


"Rasjid Wilcox" <rasjidw at gmail.com> wrote

> I've been playing with dynamically generated classes.  In 
> particular:
>
> class ClassMaker(object):
>    def __init__(maker_self, name):
>        maker_self.name = name
>        #
>        class Foo(object):
>            def __init__(self):
>                self.parent = maker_self
>            def whoami(self):
>                print 'I am a Foo instance made by %s' % 
> self.parent.name
>        maker_self.Foo = Foo

I'd probably just define the classes in a module rather than in the
init method itself. Then pass the required class to the parent init
as an argument. But the example code doesn't give enough clue
as to how these classes will be used to be sure that will suit
your need.

>>>> a = ClassMaker('Alice')
>>>> af = a.Foo()
>>>> ab = a.Bar()
>>>> af.whoami()
> I am a Foo instance made by Alice
>>>> ab.whoami()
> I am a Bar instance made by Alice
>>>> a.Foo is b.Foo
> False

> The actual use case is a system where there are multiple databases 
> of
> essentially the same form, where a is database A, and b is database 
> B,
> and Foo and Bar represent tables in both the databases.

Unless you are actually building a database it would be unusual to 
have
a class represent a table, a table normally represents a class - ie 
its not
a two way relation - or the class uses a table to populate attributes.
But again we have no clues about what the classes actually do - its
normally the methods of the class that define its usage...

> the Foo table in database A, and bf would be the Foo table in 
> database
> B.

That sounds like you may be trying to create a facade pattern?

> My question is: is there a better way?  Based on my playing with the
> above, it all seems to do what I want.  My only concern is that I've
> not seen this idiom before, and perhaps there is a simpler or more
> standard way?

I think it will do what you want but I wouldn't bother putting the 
class
definitions inside the init - unless there is a good reason. At the 
very
least I would create two factory methods which are called by init.
That would allow you to reset the classes if needed too.

class A:
  def __init__(self, name):
        self.foo = makeFoo()
        self.bar = makeBar()
  def makeFoo(self):
         class Foo: pass
         return Foo
  def makeBar(self):
         class Bar: pass
         reurn Bar

But I still think its much more flexible to define the classes in a
separate module:

import foo, bar

class A:
    def __init__(self,foo,bar):
         self.foo = foo
         self.bar = bar

a = A(foo.Foo(A),bar.Bar(A))  # pass A so Foo/Bar know their parent

You can then extend the use of A without changing A by defining
new derivatives of Foo and Bar (as you use new databases for
example)

HTH,

-- 
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/




More information about the Tutor mailing list