Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-24 Thread Joe Strout

On Nov 24, 2008, at 11:10 AM, Matimus wrote:


I wrote this a while ago. I sort of regret it though. Mixins could
(and I will argue should) be avoided most of the time by delegating to
other objects with less functionality. Utilizing many mixin classes
tends to just make gigantic classes. This is a huge violation of the
"Single Responsibility Principle".


I see your point, but in this case, I'm building a layout/config tool  
for use with wxPython, and wx uses a fair number of mixins (especially  
for the list control).



That isn't to say that I don't
think there is a place for multiple inheritance. Multiple inheritance
to the point where it is easier to write a metaclass to automatically
generate your __init__ method than it is to write it yourself is a
good indicator that you have gone too far. Which is what I did.


I appreciate the sample code, and the thoughtful comments.  You do  
yourself credit.


Best,
- Joe

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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-24 Thread Matimus
On Nov 21, 2:11 pm, Joe Strout <[EMAIL PROTECTED]> wrote:
> I have a function that takes a reference to a class, and then  
> instantiates that class (and then does several other things with the  
> new instance).  This is easy enough:
>
>     item = cls(self, **itemArgs)
>
> where "cls" is the class reference, and itemArgs is obviously a set of  
> keyword arguments for its __init__ method.
>
> But now I want to generalize this to handle a set of mix-in classes.  
> Normally you use mixins by creating a class that derives from two or  
> more other classes, and then instantiate that custom class.  But in my  
> situation, I don't know ahead of time which mixins might be used and  
> in what combination.  So I'd like to take a list of class references,  
> and instantiate an object that derives from all of them, dynamically.
>
> Is this possible?  If so, how?
>
> Thanks,
> - Joe

I wrote this a while ago. I sort of regret it though. Mixins could
(and I will argue should) be avoided most of the time by delegating to
other objects with less functionality. Utilizing many mixin classes
tends to just make gigantic classes. This is a huge violation of the
"Single Responsibility Principle". That isn't to say that I don't
think there is a place for multiple inheritance. Multiple inheritance
to the point where it is easier to write a metaclass to automatically
generate your __init__ method than it is to write it yourself is a
good indicator that you have gone too far. Which is what I did.

code:

import inspect

class AutoGenInitMetaError(Exception):
""" Exception is raised if AutoGenInitMeta cannot auto-generate a
constructor for a class because of conflicting parameters in base
classes.
"""
pass

class AutoGenInitMeta(type):
""" Meta-Class for automatically generating __init__ method for a
class
with multiple mixin base classes.
"""
def __new__(cls, name, bases, assoc):
if "__init__" in assoc:
return super(AutoGenInitMeta, cls).__new__(cls, name,
bases, assoc)
args = ['self']
dargs = []
defaults = []
tmpl = []
varg = None
vkwarg = None
tmpl = ["def __init__%s:\n"]
for base in bases[::-1]:
a, va, vkw, d = argspec = inspect.getargspec
(base.__init__)
argspecfmt = inspect.formatargspec(*argspec[:3])
if d:
num_d = len(d)
args += a[1:-num_d]
defaults += d
dargs += a[-num_d:]
else:
# remember to stip off self
args += a[1:]
if va is not None:
if varg is not None:
raise AutoGenInitMetaError(
"There must be only one `*` arg in base
constructors"
)
varg = va

if vkw is not None:
if vkwarg is not None:
raise AutoGenInitMetaError(
"There must be only one `**` arg in base
constructors"
)
vkwarg = vkw
tmpl.append("%s.__init__%s\n"%(base.__name__,
argspecfmt))
tmpl = "".join(tmpl)
argspec = (args + dargs, varg, vkwarg, defaults)
exec tmpl%inspect.formatargspec(*argspec) in globals(), assoc

return super(AutoGenInitMeta, cls).__new__(cls, name, bases,
assoc)


How do you use it?

>>> class C(object):
... def __init__(self, a, b):
... self.a = a
... self.b = b
...
>>> class D(object):
... def __init__(self, c, d):
... self.c = c
... self.d = d
...
>>> class CD(C, D):
... __metaclass__ = AutoGenInitMeta
...
>>>
>>> x = CD(1,2,3,4)
>>>
>>> x.a
3
>>> x.b
4
>>> x.c
1
>>> x.d
2
>>>

Notice that the arguments to D came before C. So you have to list the
classes in reverse order of how you want the arguments listed.

I post it as an example of a "neat python trick". Even the "neat"
might be self indulgence. I encourage anybody tempted to use this to
refactor/redesign instead.

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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-23 Thread Rafe
On Nov 22, 9:02 am, Steven D'Aprano <[EMAIL PROTECTED]
cybersource.com.au> wrote:
> On Fri, 21 Nov 2008 15:11:20 -0700, Joe Strout wrote:
> > I have a function that takes a reference to a class,
>
> Hmmm... how do you do that from Python code? The simplest way I can think
> of is to extract the name of the class, and then pass the name as a
> reference to the class, and hope it hasn't been renamed in the meantime:
>
> def foo(cls_name, item_args):
>     # Won't necessarily work for nested scopes.
>     cls = globals()[cls_name]
>     item = cls(**itemArgs)
>     return item
>
> instance = foo(Myclass.__name__, {'a':1})
>
> Seems awfully complicated. If I were you, I'd forget the extra layer of
> indirection and just pass the class itself, rather than trying to
> generate some sort of reference to it. Let the Python virtual machine
> worry about what is the most efficient mechanism to use behind the scenes.
>
> [...]
>
> > But now I want to generalize this to handle a set of mix-in classes.
> > Normally you use mixins by creating a class that derives from two or
> > more other classes, and then instantiate that custom class.  But in my
> > situation, I don't know ahead of time which mixins might be used and in
> > what combination.  So I'd like to take a list of class references, and
> > instantiate an object that derives from all of them, dynamically.
>
> > Is this possible?  If so, how?
>
> It sounds like you need to generate a new class on the fly. Here's one
> way:
>
> # untested
> def foo(cls, item_args, mixins=None):
>     superclasses = [cls] + (mixins or [])
>     class MixedClass(*superclasses):
>         pass
>     item = MixedClass(**itemArgs)
>     return item
>
> instance = foo(MyClass, {'a':1}, [Aclass, Bclass, Cclass])
>
> --
> Steven

I find type() is the better way to go because it allows you to name
the resulting class as well. It may make debugging a little easier.
Using a hard-coded class, such as "MixedClass" in the above example,
with dynamic bases produces lots of "MixedClass" instances with
different interfaces/abilities.

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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-22 Thread George Sakkis
On Nov 22, 9:32 am, Joe Strout <[EMAIL PROTECTED]> wrote:
> On Nov 21, 2008, at 7:02 PM, Steven D'Aprano wrote:
>
> >> I have a function that takes a reference to a class,
>
> > Hmmm... how do you do that from Python code? The simplest way I can  
> > think
> > of is to extract the name of the class, and then pass the name as a
> > reference to the class, and hope it hasn't been renamed in the  
> > meantime...
>
> Please quit trying to confuse the kids at home.  Classes in Python are  
> first-class objects, and any time you refer to a class or any other  
> object in Python, what you have is a reference to it.

..which makes the phrase "a reference to an X" a more verbose,
redundant version of "an X" since it applies to *every* Python object.
You have made your point in the 300+ posts thread, so please quit the
terminology trolling in every new thread.

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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-22 Thread Steven D'Aprano
On Sat, 22 Nov 2008 07:32:07 -0700, Joe Strout wrote:

> On Nov 21, 2008, at 7:02 PM, Steven D'Aprano wrote:
> 
>>> I have a function that takes a reference to a class,
>>
>> Hmmm... how do you do that from Python code? The simplest way I can
>> think
>> of is to extract the name of the class, and then pass the name as a
>> reference to the class, and hope it hasn't been renamed in the
>> meantime...
> 
> Please quit trying to confuse the kids at home. Classes in Python are
> first-class objects, and any time you refer to a class or any other
> object in Python, what you have is a reference to it.


No, at the level of Python code, what you have is the object itself.

What any specific implementation of the Python virtual machine almost 
certainly will have are references, or pointers, or some other 
implementation-specific form of indirection that eventually leads to the 
object. But at the level of Python code, they are invisible. There are no 
references at the level of Python code.

The burden of proof lies on you to prove that "reference to a class" has 
any meaning at the level of Python code. First you need to define what a 
reference is, in terms of *Python* entities (not implementation details), 
how it differs from the object itself, and how you can tell "a reference 
to a class" apart from the class itself, *at the level of Python code*.

I don't think you can do it, not without conflating implementation-level 
details with Python-level details. In Python code, you have objects, and 
that is all. Talking about "a reference to a class" instead of "a class" 
is simply obscurantism.



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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-22 Thread Arnaud Delobelle
Joe Strout <[EMAIL PROTECTED]> writes:

> On Nov 21, 2008, at 7:02 PM, Steven D'Aprano wrote:
>
>>> I have a function that takes a reference to a class,
>>
>> Hmmm... how do you do that from Python code? The simplest way I can
>> think
>> of is to extract the name of the class, and then pass the name as a
>> reference to the class, and hope it hasn't been renamed in the
>> meantime...
>
> Please quit trying to confuse the kids at home.  Classes in Python are
> first-class objects, and any time you refer to a class or any other
> object in Python, what you have is a reference to it.
>
>

Why don't you put this link in your sig?  It'll save you time.  If I
were you though I would wait a bit until I have had more experience with
Python (In case you change your mind).

In the meantime why not adopt the terminology commonly used on this list
and by Python users at large?  Nobody else would talk about 'a function
that takes a reference to a class'.  It's just plain confusing.

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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-22 Thread Joe Strout

On Nov 21, 2008, at 7:02 PM, Steven D'Aprano wrote:


I have a function that takes a reference to a class,


Hmmm... how do you do that from Python code? The simplest way I can  
think

of is to extract the name of the class, and then pass the name as a
reference to the class, and hope it hasn't been renamed in the  
meantime...


Please quit trying to confuse the kids at home.  Classes in Python are  
first-class objects, and any time you refer to a class or any other  
object in Python, what you have is a reference to it.


   

Cheers,
- Joe

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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-21 Thread Steven D'Aprano
On Fri, 21 Nov 2008 15:11:20 -0700, Joe Strout wrote:

> I have a function that takes a reference to a class, 

Hmmm... how do you do that from Python code? The simplest way I can think 
of is to extract the name of the class, and then pass the name as a 
reference to the class, and hope it hasn't been renamed in the meantime:

def foo(cls_name, item_args):
# Won't necessarily work for nested scopes.
cls = globals()[cls_name]
item = cls(**itemArgs)
return item

instance = foo(Myclass.__name__, {'a':1})

Seems awfully complicated. If I were you, I'd forget the extra layer of 
indirection and just pass the class itself, rather than trying to 
generate some sort of reference to it. Let the Python virtual machine 
worry about what is the most efficient mechanism to use behind the scenes.


[...]
> But now I want to generalize this to handle a set of mix-in classes.
> Normally you use mixins by creating a class that derives from two or
> more other classes, and then instantiate that custom class.  But in my
> situation, I don't know ahead of time which mixins might be used and in
> what combination.  So I'd like to take a list of class references, and
> instantiate an object that derives from all of them, dynamically.
> 
> Is this possible?  If so, how?

It sounds like you need to generate a new class on the fly. Here's one 
way:

# untested
def foo(cls, item_args, mixins=None):
superclasses = [cls] + (mixins or [])
class MixedClass(*superclasses):
pass
item = MixedClass(**itemArgs)
return item

instance = foo(MyClass, {'a':1}, [Aclass, Bclass, Cclass])


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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-21 Thread Steve Holden
Joe Strout wrote:
> On Nov 21, 2008, at 6:06 PM, Ned Deily wrote:
> 
>>> Where would I find documentation on this nifty function?
>>
>> Where built-in functions are documented, the Python Library Reference:
>>
>> 
> 
> Perfect, thank you.  (Odd that the index entry for type() doesn't link
> to this page.)

Yeah, the indexing isn't perfect. Not sure what to do about that without
filing bugs for each case (which I am as guilty of not doing as anyone
else).

regards
 Steve
-- 
Steve Holden+1 571 484 6266   +1 800 494 3119
Holden Web LLC  http://www.holdenweb.com/

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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-21 Thread Joe Strout

On Nov 21, 2008, at 6:06 PM, Ned Deily wrote:


Where would I find documentation on this nifty function?


Where built-in functions are documented, the Python Library Reference:




Perfect, thank you.  (Odd that the index entry for type() doesn't link  
to this page.)


Best,
- Joe


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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-21 Thread Ned Deily
In article <[EMAIL PROTECTED]>,
 Joe Strout <[EMAIL PROTECTED]> wrote:
> On Nov 21, 2008, at 3:30 PM, Arnaud Delobelle wrote:
> > Of course it's possible: use type(name, bases, dict).
> Thanks, I never knew about that form of type().  Neither does the  
> 2.5.2 reference manual, whose only index entry for the type() function  
> is , and that  
> speaks only about the traditional use of type() to check the type of  
> an object.
> 
> help(type) does mention the form you show, though it doesn't explain  
> what the dict is for.
> 
> Where would I find documentation on this nifty function?

Where built-in functions are documented, the Python Library Reference:



-- 
 Ned Deily,
 [EMAIL PROTECTED]

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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-21 Thread Joe Strout

On Nov 21, 2008, at 3:30 PM, Arnaud Delobelle wrote:


Of course it's possible: use type(name, bases, dict).


Thanks, I never knew about that form of type().  Neither does the  
2.5.2 reference manual, whose only index entry for the type() function  
is , and that  
speaks only about the traditional use of type() to check the type of  
an object.


help(type) does mention the form you show, though it doesn't explain  
what the dict is for.


Where would I find documentation on this nifty function?

Thanks,
- Joe


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


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-21 Thread George Sakkis
On Nov 21, 5:11 pm, Joe Strout <[EMAIL PROTECTED]> wrote:
> I have a function that takes a reference to a class, and then  
> instantiates that class (and then does several other things with the  
> new instance).  This is easy enough:
>
>     item = cls(self, **itemArgs)
>
> where "cls" is the class reference, and itemArgs is obviously a set of  
> keyword arguments for its __init__ method.
>
> But now I want to generalize this to handle a set of mix-in classes.  
> Normally you use mixins by creating a class that derives from two or  
> more other classes, and then instantiate that custom class.  But in my  
> situation, I don't know ahead of time which mixins might be used and  
> in what combination.  So I'd like to take a list of class references,  
> and instantiate an object that derives from all of them, dynamically.
>
> Is this possible?  If so, how?

Easily:

derived_cls = type('Derived', (cls1, cls2, *rest_classes), {})
item = derived_cls(**itemArgs)

You will probably want to cache the generated classes so that at most
one class is created for each combination of mixins.

HTH,
George
--
http://mail.python.org/mailman/listinfo/python-list


Re: how to dynamically instantiate an object inheriting from several classes?

2008-11-21 Thread Arnaud Delobelle
Joe Strout <[EMAIL PROTECTED]> writes:

> I have a function that takes a reference to a class, and then
> instantiates that class (and then does several other things with the
> new instance).  This is easy enough:
>
>item = cls(self, **itemArgs)
>
> where "cls" is the class reference, and itemArgs is obviously a set of
> keyword arguments for its __init__ method.
>
> But now I want to generalize this to handle a set of mix-in classes.
> Normally you use mixins by creating a class that derives from two or
> more other classes, and then instantiate that custom class.  But in my
> situation, I don't know ahead of time which mixins might be used and
> in what combination.  So I'd like to take a list of class references,
> and instantiate an object that derives from all of them, dynamically.
>
> Is this possible?  If so, how?

Of course it's possible: use type(name, bases, dict).

>>> class A(object): pass
... 
>>> class B(object): pass
... 
>>> C = type('C', (A, B), {})
>>> issubclass(C, A)
True
>>> issubclass(C, B)
True

Call-by-object'ly yours

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


how to dynamically instantiate an object inheriting from several classes?

2008-11-21 Thread Joe Strout
I have a function that takes a reference to a class, and then  
instantiates that class (and then does several other things with the  
new instance).  This is easy enough:


   item = cls(self, **itemArgs)

where "cls" is the class reference, and itemArgs is obviously a set of  
keyword arguments for its __init__ method.


But now I want to generalize this to handle a set of mix-in classes.   
Normally you use mixins by creating a class that derives from two or  
more other classes, and then instantiate that custom class.  But in my  
situation, I don't know ahead of time which mixins might be used and  
in what combination.  So I'd like to take a list of class references,  
and instantiate an object that derives from all of them, dynamically.


Is this possible?  If so, how?

Thanks,
- Joe

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