dynamic

R

Riccardo Galli

Hi all.
It's easier if I show an example first.

Say I have

class A(object):
def speak(self): print 'A!'

class B(object):
def speak(self): print 'B!'

I also have a factory function like this.

def foo(kind,*args,**kwds):
if kind=='a': return A(*args,**kwds)
else: return B(*args,**kwds)

I need foo to be a class, so that I could inherit from it and still use
it as a factory, so that I can do:

Foo('a').speak()
Foo('b'.speak()

class Final(Foo):
def __init__(self,kind,*args,**kwds):
super(Foo,self).__init__(kind,*args,*kwds)

Can I do it? How ?
If it is possible, I'm pretty sure it involves using __new__ on Foo, but I
can't figure out how to make it works.

Any help is appreciated.

Thank you,
Riccardo
 
M

Michele Simionato

Having a class that returns instances
of some other class is horrible, but
since you asked for it:

class A(object): pass
class B(object): pass

class Foo(object):
def __new__(cls, arg):
if arg=="a":
return A()
else:
return B()

print Foo("a")
print Foo("b")

Michele Simionato

P.S. don't do it!
 
R

Riccardo Galli

Having a class that returns instances of some other class is horrible, but
since you asked for it:

class A(object): pass
class B(object): pass

class Foo(object):
def __new__(cls, arg):
if arg=="a":
return A()
else:
return B()

print Foo("a")
print Foo("b")

Michele Simionato

P.S. don't do it!

Ciao Michele.

I have n classes wich share the same interface.
I then have a single class which add functionality to all the n classes,
using their interface.
The only way I see to make this single class inherith from the choosed nx
class is this one.

If there is a better approach, I can implement it.

Thank you for the answer,
Riccardo
 
D

Dan Sommers

I have n classes wich share the same interface. I then have a single
class which add functionality to all the n classes, using their
interface. The only way I see to make this single class inherith from
the choosed nx class is this one.
If there is a better approach, I can implement it.

class single(object):
pass

class n1(single):
pass
class n2(single):
pass
class n3(single):
pass

HTH,
Dan
 
K

Kent Johnson

Riccardo said:
Hi all.
It's easier if I show an example first.

Say I have

class A(object):
def speak(self): print 'A!'

class B(object):
def speak(self): print 'B!'

I also have a factory function like this.

def foo(kind,*args,**kwds):
if kind=='a': return A(*args,**kwds)
else: return B(*args,**kwds)

I need foo to be a class, so that I could inherit from it and still use
it as a factory, so that I can do:

Foo('a').speak()
Foo('b'.speak()

class Final(Foo):
def __init__(self,kind,*args,**kwds):
super(Foo,self).__init__(kind,*args,*kwds)

I'm not clear why you want to do this. Presumably you want to be able to say
Final('a').speak() ??
How will this differ from
Foo('a').speak()
Why does Final need to subclass Foo?

Can you use either of these syntaxes? Either one can be specialized in a subclass:
Foo()('a').speak() # use Foo.__call__() as factory
Foo.make('a') # Use classmethod as factory

Kent
 
?

=?iso-8859-1?Q?Fran=E7ois?= Pinard

[Michele Simionato]
Having a class that returns instances of some other class is horrible,
[...] don't do it!

Unusual, granted. Horrible, why?

I found useful, sometimes, (ab)using Python syntax for representing data
having more or less complex structure. More than once, it spared me the
trouble of inventing a syntax, and then writing a lexer and a parser.
Letting class constructors returning arbitrary objects has often been
useful in such circumstances.
 
J

James Carroll

Returning instances of some other class is not so horrible. They're
called FactoryMethods usually.

An example is when you have a polymorphic tree of image file reader
objects, and you open an image file, it might return a JpegReader
which ISA ImageReader or a TIFFReader which also ISA ImageReader, but
you want all of the 'which class do I need for this data?' logic to
be in one place.

-Jim
 
S

Scott David Daniels

Riccardo Galli wrote (approximately):
I need a class to behave as a factory method for its children so that I could inherit
> from it and still use it as a factory.

Several others suggest you probably don't want to do this; I concur.
Separating the factory from the interface (I presume you are doing some
isinstance checking) is probably a good idea. If, for some reason, you
feel you must implement your original plan, the following code should
outline the trick (look up __new__ and study the code).


class Interf(object):
def __new__(klass, kind, *args, **kwargs):
if kind is None:
return object.__new__(klass, *args, **kwargs)
elif kind == 'a':
return Sub1(*args, **kwargs)
else:
assert kind == 'b'
return Sub2(*args, **kwargs)
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, ', '.join(
'%s=%r' % pair
for pair in sorted(vars(self).items())))

class Sub1(Interf):
def __new__(klass, *args, **kwargs):
return Interf.__new__(klass, None, *args, **kwargs)
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs

class Sub2(Interf):
def __new__(klass, *args, **kwargs):
return Interf.__new__(klass, None, *args, **kwargs)
def __init__(self, *args, **kwargs):
self.xargs = args
self.xkwargs = kwargs

--Scott David Daniels
(e-mail address removed)
 
M

Michele Simionato

Yes, factory methods, exactly. If I had a base class ImageReader with
children JpegReader and TIFFReader, I will probably add two factory
methods ImageReader.makeJpegReader and ImageReader.makeTIFFReader, I
will not override ImageReader.__new__
to return sometimes JpegReader instances and sometimes TIFFReader
instances. Explicit is better than implicit and all that.

Michele Simionato
 
M

Michele Simionato

I think using __new__ when a plain old factory method would
work is horrible. But I am not saying that there no use cases for
__new__. I used it once, when I wanted a class working
for the final user as a factory function. I just wrote the class in
lower case and gave it a custom __new__ method.

Michele Simionato
 
J

James Carroll

Oh, I see. Yeah, having the code look like you're instantiating one
class, but really getting a different one is really horrible. Sorry I
didn't catch on to the subtlety. I'm always complaining about code
that looks like it does one thing, but really does another.

-Jim
 
R

Riccardo Galli

On Wed, 15 Jun 2005 11:50:27 +0200, Riccardo Galli wrote:

Hi.
Thanks to all who answered.

Scott David posted a solution (clever, scott) which was what I asked for,
but I noticed some oddness while using it (about __init__).
I also understood that this way should be avoided.

I ended up using a proxy approach, wich works.

Thank you,
Riccardo
 

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,774
Messages
2,569,598
Members
45,155
Latest member
JuliW73391
Top