runtime inheritance (e.g. __new__, __metaclass__)

H

H Jansen

I try to work out how to use __new__ and metaclass (or __metaclass__)
mechanisms in order to change the base class at runtime. I haven't been
successful so far, however, even after also reading most of the relevant
documentation.

The most simple representation (an oversimplification indeed) of what
I'm trying to accomplish is this:

class Base1:
pass

class Base2:
pass

class Meta:
pass

class Good(Meta):
pass

What I want to achieve at runtime is this:

g1 = Good(Base1) # a Good object with base class Base1
g2 = Good(Base2) # a Good object with base class Base2

Of course, this oversimplified (pseudo-code) example will not work but
illustrates most clearly my idea. How can I come closest to realizing
this by using the above mechanisms?


Thanks

--Henk


--
 
P

Peter Otten

H said:
I try to work out how to use __new__ and metaclass (or __metaclass__)
mechanisms in order to change the base class at runtime. I haven't been
successful so far, however, even after also reading most of the relevant
documentation.

The most simple representation (an oversimplification indeed) of what
I'm trying to accomplish is this:

class Base1:
pass

class Base2:
pass

class Meta:
pass

class Good(Meta):
pass

What I want to achieve at runtime is this:

g1 = Good(Base1) # a Good object with base class Base1
g2 = Good(Base2) # a Good object with base class Base2

Of course, this oversimplified (pseudo-code) example will not work but
illustrates most clearly my idea. How can I come closest to realizing
this by using the above mechanisms?
.... class Derived(base):
.... pass
.... return Derived()
....True

:)

Seriously, either too much information was lost in the simplification
process or you want to have instances of the same class with different
bases - which doesn't seem possible to me as the __bases__ attribute is in
the class, not the instance. On the other hand, changing base classes at
runtime is as simple as assigning __bases__.
__new__() can serve as a factory that returns objects of an arbitrary type,
but I don't consider that good style. Metaclasses - no idea where they
could enter the picture.


Peter
 
S

Steven Bethard

H Jansen said:
What I want to achieve at runtime is this:

g1 = Good(Base1) # a Good object with base class Base1
g2 = Good(Base2) # a Good object with base class Base2

Peter's solution is clean (and the way I'd go) as long as you don't
mind Good being a function, not a class. If you need Good to be a
class, you could probably get what you want by changing the __bases__
attribute:
.... def __init__(self):
.... print "Base1"
.... .... def __init__(self):
.... print "Base2"
.... .... pass
....
Base2
<__main__.Good instance at 0x00E6DC38>

Note that once you've changed the base classes of the Good class,
you'll have to change them back if you want the original behavior
again.

Or if you actually need different Good classes, you could try
something like:
.... def __init__(self):
.... print "Base1"
.... .... def __init__(self):
.... print "Base2"
.... .... pass
....
Base2
<__main__.Good2 object at 0x00E66450>

Note that type.__new__ requires a dict (not a dictproxy like the
__dict__ attribute), so I've copied the Good.__dict__ attribute
instead of having both classes reference the same one. This means
that if you have a class variable in Good (and therefore in Good1 and
Good2), if you modify it in Good1, it will not be modified in Good2,
e.g.:
1

This may or may not be desirable.

This technique does seem to transfer any methods successfully:
.... def f(self, x):
.... print (self.__class__, x)
....
Base2
(<class '__main__.Good2'>, 2)

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top