By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,235 Members | 1,008 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,235 IT Pros & Developers. It's quick & easy.

dynamic

P: n/a
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

--
Riccardo Galli
Sideralis Programs
http://www.sideralis.net
Jul 19 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
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!

Jul 19 '05 #2

P: n/a
On Wed, 15 Jun 2005 03:12:07 -0700, Michele Simionato wrote:
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

--
Riccardo Galli
Sideralis Programs
http://www.sideralis.net
Jul 19 '05 #3

P: n/a
On Wed, 15 Jun 2005 13:13:49 +0200,
Riccardo Galli <riccardo_cut1@cut2_sideralis.net> wrote:
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

--
Dan Sommers
<http://www.tombstonezero.net/dan/>
Jul 19 '05 #4

P: n/a
Riccardo Galli wrote:
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
Jul 19 '05 #5

P: n/a
[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.

--
François Pinard http://pinard.progiciels-bpi.ca
Jul 19 '05 #6

P: n/a
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

On 15 Jun 2005 03:12:07 -0700, Michele Simionato
<mi***************@gmail.com> wrote:
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!

--
http://mail.python.org/mailman/listinfo/python-list

Jul 19 '05 #7

P: n/a
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
Sc***********@Acm.Org
Jul 19 '05 #8

P: n/a
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

Jul 19 '05 #9

P: n/a
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

Jul 19 '05 #10

P: n/a
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

On 15 Jun 2005 22:24:28 -0700, Michele Simionato
<mi***************@gmail.com> wrote:
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

--
http://mail.python.org/mailman/listinfo/python-list

Jul 19 '05 #11

P: n/a
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

--
Riccardo Galli
Sideralis Programs
http://www.sideralis.net
Jul 19 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.